use serde::Deserialize;
use serde::de::{self, Deserializer, SeqAccess, Visitor};
use std::convert::Infallible;
use std::fmt;
use std::marker::PhantomData;
use std::str::FromStr;
pub fn empty_or_none(value: &Option<String>) -> bool {
value.as_ref().map(|v| v.is_empty()).unwrap_or(true)
}
pub fn merge(a: serde_json::Value, b: serde_json::Value) -> serde_json::Value {
match (a, b) {
(serde_json::Value::Object(mut a_map), serde_json::Value::Object(b_map)) => {
b_map.into_iter().for_each(|(key, value)| {
a_map.insert(key, value);
});
serde_json::Value::Object(a_map)
}
(a, _) => a,
}
}
pub fn merge_inplace(a: &mut serde_json::Value, b: serde_json::Value) {
if let (serde_json::Value::Object(a_map), serde_json::Value::Object(b_map)) = (a, b) {
b_map.into_iter().for_each(|(key, value)| {
a_map.insert(key, value);
});
}
}
pub fn value_to_json_string(value: &serde_json::Value) -> String {
match value {
serde_json::Value::String(s) => s.clone(),
other => other.to_string(),
}
}
pub fn parse_tool_arguments(arguments: &str) -> serde_json::Result<serde_json::Value> {
if arguments.trim().is_empty() {
return Ok(serde_json::Value::Object(serde_json::Map::new()));
}
serde_json::from_str(arguments)
}
pub mod stringified_json {
use super::parse_tool_arguments;
use serde::{self, Deserialize, Deserializer, Serializer};
pub fn serialize<S>(value: &serde_json::Value, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = value.to_string();
serializer.serialize_str(&s)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<serde_json::Value, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
if s.trim().is_empty() {
return Ok(serde_json::Value::Object(serde_json::Map::new()));
}
serde_json::from_str(&s).map_err(serde::de::Error::custom)
}
pub fn deserialize_maybe_stringified<'de, D>(
deserializer: D,
) -> Result<serde_json::Value, D::Error>
where
D: Deserializer<'de>,
{
match serde_json::Value::deserialize(deserializer)? {
serde_json::Value::String(s) => {
parse_tool_arguments(&s).map_err(serde::de::Error::custom)
}
other => Ok(other),
}
}
}
pub fn string_or_vec<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
where
T: Deserialize<'de> + FromStr<Err = Infallible>,
D: Deserializer<'de>,
{
struct StringOrVec<T>(PhantomData<fn() -> T>);
impl<'de, T> Visitor<'de> for StringOrVec<T>
where
T: Deserialize<'de> + FromStr<Err = Infallible>,
{
type Value = Vec<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string, sequence, or null")
}
fn visit_str<E>(self, value: &str) -> Result<Vec<T>, E>
where
E: de::Error,
{
let item = FromStr::from_str(value).map_err(de::Error::custom)?;
Ok(vec![item])
}
fn visit_seq<A>(self, seq: A) -> Result<Vec<T>, A::Error>
where
A: SeqAccess<'de>,
{
Deserialize::deserialize(de::value::SeqAccessDeserializer::new(seq))
}
fn visit_none<E>(self) -> Result<Vec<T>, E>
where
E: de::Error,
{
Ok(vec![])
}
fn visit_unit<E>(self) -> Result<Vec<T>, E>
where
E: de::Error,
{
Ok(vec![])
}
}
deserializer.deserialize_any(StringOrVec(PhantomData))
}
pub fn null_or_vec<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
struct NullOrVec<T>(PhantomData<fn() -> T>);
impl<'de, T> Visitor<'de> for NullOrVec<T>
where
T: Deserialize<'de>,
{
type Value = Vec<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence or null")
}
fn visit_seq<A>(self, seq: A) -> Result<Vec<T>, A::Error>
where
A: SeqAccess<'de>,
{
Deserialize::deserialize(de::value::SeqAccessDeserializer::new(seq))
}
fn visit_none<E>(self) -> Result<Vec<T>, E>
where
E: de::Error,
{
Ok(vec![])
}
fn visit_unit<E>(self) -> Result<Vec<T>, E>
where
E: de::Error,
{
Ok(vec![])
}
}
deserializer.deserialize_any(NullOrVec(PhantomData))
}
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Dummy {
#[serde(with = "stringified_json")]
data: serde_json::Value,
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct DummyMaybeStringified {
#[serde(deserialize_with = "stringified_json::deserialize_maybe_stringified")]
data: serde_json::Value,
}
#[test]
fn test_merge() {
let a = serde_json::json!({"key1": "value1"});
let b = serde_json::json!({"key2": "value2"});
let result = merge(a, b);
let expected = serde_json::json!({"key1": "value1", "key2": "value2"});
assert_eq!(result, expected);
}
#[test]
fn test_merge_inplace() {
let mut a = serde_json::json!({"key1": "value1"});
let b = serde_json::json!({"key2": "value2"});
merge_inplace(&mut a, b);
let expected = serde_json::json!({"key1": "value1", "key2": "value2"});
assert_eq!(a, expected);
}
#[test]
fn test_stringified_json_serialize() {
let dummy = Dummy {
data: serde_json::json!({"key": "value"}),
};
let serialized = serde_json::to_string(&dummy).unwrap();
let expected = r#"{"data":"{\"key\":\"value\"}"}"#;
assert_eq!(serialized, expected);
}
#[test]
fn test_stringified_json_deserialize() {
let json_str = r#"{"data":"{\"key\":\"value\"}"}"#;
let dummy: Dummy = serde_json::from_str(json_str).unwrap();
let expected = Dummy {
data: serde_json::json!({"key": "value"}),
};
assert_eq!(dummy, expected);
}
#[test]
fn test_stringified_json_deserialize_empty_string() {
let json_str = r#"{"data":""}"#;
let dummy: Dummy = serde_json::from_str(json_str).unwrap();
assert_eq!(dummy.data, serde_json::json!({}));
}
#[test]
fn test_deserialize_maybe_stringified_value_from_string() {
let json_str = r#"{"data":"{\"key\":\"value\"}"}"#;
let dummy: DummyMaybeStringified = serde_json::from_str(json_str).unwrap();
assert_eq!(dummy.data, serde_json::json!({"key": "value"}));
}
#[test]
fn test_deserialize_maybe_stringified_value_from_object() {
let json_str = r#"{"data":{"key":"value"}}"#;
let dummy: DummyMaybeStringified = serde_json::from_str(json_str).unwrap();
assert_eq!(dummy.data, serde_json::json!({"key": "value"}));
}
#[test]
fn test_deserialize_maybe_stringified_value_from_empty_string() {
let json_str = r#"{"data":""}"#;
let dummy: DummyMaybeStringified = serde_json::from_str(json_str).unwrap();
assert_eq!(dummy.data, serde_json::json!({}));
}
#[test]
fn test_parse_tool_arguments_empty_string() {
let parsed = parse_tool_arguments("").unwrap();
assert_eq!(parsed, serde_json::json!({}));
}
#[test]
fn test_parse_tool_arguments_whitespace_string() {
let parsed = parse_tool_arguments(" ").unwrap();
assert_eq!(parsed, serde_json::json!({}));
}
#[test]
fn test_parse_tool_arguments_valid_json() {
let parsed = parse_tool_arguments(r#"{"key":"value"}"#).unwrap();
assert_eq!(parsed, serde_json::json!({"key": "value"}));
}
}