1use serde::Deserialize;
2use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor};
3use std::convert::Infallible;
4use std::fmt;
5use std::marker::PhantomData;
6use std::str::FromStr;
7
8#[allow(clippy::trivially_copy_pass_by_ref)]
11pub(crate) fn is_false(value: &bool) -> bool {
12 !value
13}
14
15pub fn canonical(value: serde_json::Value) -> serde_json::Value {
18 match value {
19 serde_json::Value::Object(map) => {
20 let mut entries: Vec<_> = map.into_iter().collect();
21 entries.sort_by(|(left, _), (right, _)| left.cmp(right));
22 let entries = entries
23 .into_iter()
24 .map(|(key, value)| (key, canonical(value)));
25 serde_json::Value::Object(entries.collect())
26 }
27 serde_json::Value::Array(items) => {
28 serde_json::Value::Array(items.into_iter().map(canonical).collect())
29 }
30 other => other,
31 }
32}
33
34pub fn to_canonical_string(value: &serde_json::Value) -> String {
36 canonical(value.clone()).to_string()
37}
38
39pub fn merge(a: serde_json::Value, b: serde_json::Value) -> serde_json::Value {
40 match (a, b) {
41 (serde_json::Value::Object(mut a_map), serde_json::Value::Object(b_map)) => {
42 b_map.into_iter().for_each(|(key, value)| {
43 a_map.insert(key, value);
44 });
45 serde_json::Value::Object(a_map)
46 }
47 (a, _) => a,
48 }
49}
50
51pub(crate) fn merge_params(
55 existing: Option<serde_json::Value>,
56 params: Option<serde_json::Value>,
57) -> Option<serde_json::Value> {
58 Some(match (existing, params?) {
59 (Some(existing), params) => merge(existing, params),
60 (None, params) => params,
61 })
62}
63
64#[cfg_attr(not(any(feature = "image", feature = "audio")), allow(dead_code))]
66pub fn merge_inplace(a: &mut serde_json::Value, b: serde_json::Value) {
67 if let (serde_json::Value::Object(a_map), serde_json::Value::Object(b_map)) = (a, b) {
68 b_map.into_iter().for_each(|(key, value)| {
69 a_map.insert(key, value);
70 });
71 }
72}
73
74pub fn value_to_json_string(value: &serde_json::Value) -> String {
79 match value {
80 serde_json::Value::String(s) => s.clone(),
81 other => other.to_string(),
82 }
83}
84
85pub fn parse_tool_arguments(arguments: &str) -> serde_json::Result<serde_json::Value> {
88 if arguments.trim().is_empty() {
89 return Ok(serde_json::Value::Object(serde_json::Map::new()));
90 }
91
92 serde_json::from_str(arguments)
93}
94
95pub fn is_whole_object(arguments: &str) -> bool {
99 let end = arguments.trim_end();
100 (end.is_empty() || end.ends_with('}'))
101 && matches!(
102 parse_tool_arguments(arguments),
103 Ok(serde_json::Value::Object(_))
104 )
105}
106
107pub fn parse_partial_object(text: &str) -> Option<serde_json::Map<String, serde_json::Value>> {
111 const MAX_ATTEMPTS: usize = 256;
114 let mut stack = Vec::new();
115 let mut in_string = false;
116 let mut escaped = false;
117 let mut cuts: Vec<(usize, Vec<u8>, bool)> = Vec::new();
119 let bytes = text.as_bytes();
120 for (at, byte) in bytes.iter().enumerate() {
121 if in_string {
122 match (escaped, *byte) {
123 (true, _) => escaped = false,
124 (false, b'\\') => escaped = true,
125 (false, b'"') => {
126 in_string = false;
127 cuts.push((at + 1, stack.clone(), false));
128 }
129 (false, _) => {}
130 }
131 continue;
132 }
133 match byte {
134 b'"' => in_string = true,
135 b'{' | b'[' => {
136 stack.push(*byte);
137 cuts.push((at + 1, stack.clone(), false));
138 }
139 b'}' | b']' => {
140 stack.pop();
141 cuts.push((at + 1, stack.clone(), false));
142 }
143 b if b.is_ascii_alphanumeric() || *b == b'.' || *b == b'-' || *b == b'+' => {
144 let next = bytes.get(at + 1).copied();
145 if !next.is_some_and(|n| {
146 n.is_ascii_alphanumeric() || n == b'.' || n == b'-' || n == b'+'
147 }) {
148 cuts.push((at + 1, stack.clone(), false));
149 }
150 }
151 _ => {}
152 }
153 }
154 if in_string {
155 let at = text.len() - usize::from(escaped);
156 cuts.push((at, stack.clone(), true));
157 }
158 cuts.iter()
159 .rev()
160 .take(MAX_ATTEMPTS)
161 .find_map(|(at, open, quote)| {
162 let mut candidate = text.get(..*at)?.to_owned();
163 if *quote {
164 candidate.push('"');
165 }
166 for container in open.iter().rev() {
167 candidate.push(if *container == b'{' { '}' } else { ']' });
168 }
169 match serde_json::from_str(&candidate) {
170 Ok(serde_json::Value::Object(object)) => Some(object),
171 _ => None,
172 }
173 })
174}
175
176pub fn parse_partial_arguments(text: &str) -> serde_json::Map<String, serde_json::Value> {
194 if text.trim().is_empty() {
195 return serde_json::Map::new();
196 }
197 let repaired = repair_json(text);
198 let complete = serde_json::from_str(text)
199 .ok()
200 .or_else(|| serde_json::from_str(&repaired).ok());
201 if let Some(value) = complete {
202 return match value {
203 serde_json::Value::Object(object) => object,
204 _ => serde_json::Map::new(),
205 };
206 }
207 let cut = without_partial_escape(&repaired);
208 parse_partial_object(cut)
209 .or_else(|| parse_partial_object(text))
210 .unwrap_or_default()
211}
212
213fn repair_json(text: &str) -> String {
217 let mut repaired = String::with_capacity(text.len());
218 let mut in_string = false;
219 let mut chars = text.chars().peekable();
220 while let Some(c) = chars.next() {
221 if !in_string {
222 in_string = c == '"';
223 repaired.push(c);
224 continue;
225 }
226 match c {
227 '"' => {
228 in_string = false;
229 repaired.push(c);
230 }
231 '\\' => match chars.peek() {
232 Some('"' | '\\' | '/' | 'b' | 'f' | 'n' | 'r' | 't' | 'u') => {
233 repaired.push(c);
234 if let Some(next) = chars.next() {
235 repaired.push(next);
236 }
237 }
238 None => repaired.push(c),
240 Some(_) => repaired.push_str("\\\\"),
241 },
242 '\n' => repaired.push_str("\\n"),
243 '\r' => repaired.push_str("\\r"),
244 '\t' => repaired.push_str("\\t"),
245 c if c.is_control() => {
246 use std::fmt::Write as _;
247 let _ = write!(repaired, "\\u{:04x}", u32::from(c));
249 }
250 c => repaired.push(c),
251 }
252 }
253 repaired
254}
255
256fn without_partial_escape(text: &str) -> &str {
259 let bytes = text.as_bytes();
260 let tail = bytes.len().saturating_sub(5);
261 let Some(at) = (tail..bytes.len())
262 .rev()
263 .find(|at| bytes.get(*at..*at + 2) == Some(b"\\u"))
264 else {
265 return text;
266 };
267 let digits = bytes.get(at + 2..).unwrap_or_default();
268 let escaping = bytes
270 .get(..at)
271 .unwrap_or_default()
272 .iter()
273 .rev()
274 .take_while(|byte| **byte == b'\\')
275 .count();
276 if digits.len() < 4 && digits.iter().all(u8::is_ascii_hexdigit) && escaping % 2 == 0 {
277 text.get(..at).unwrap_or(text)
278 } else {
279 text
280 }
281}
282
283pub fn string_or_vec<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
286where
287 T: Deserialize<'de> + FromStr<Err = Infallible>,
288 D: Deserializer<'de>,
289{
290 struct StringOrVec<T>(PhantomData<fn() -> T>);
291
292 impl<'de, T> Visitor<'de> for StringOrVec<T>
293 where
294 T: Deserialize<'de> + FromStr<Err = Infallible>,
295 {
296 type Value = Vec<T>;
297
298 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
299 formatter.write_str("a string, sequence, or null")
300 }
301
302 fn visit_str<E>(self, value: &str) -> Result<Vec<T>, E>
303 where
304 E: de::Error,
305 {
306 let item = FromStr::from_str(value).map_err(de::Error::custom)?;
307 Ok(vec![item])
308 }
309
310 fn visit_seq<A>(self, seq: A) -> Result<Vec<T>, A::Error>
311 where
312 A: SeqAccess<'de>,
313 {
314 Deserialize::deserialize(de::value::SeqAccessDeserializer::new(seq))
315 }
316
317 fn visit_map<M>(self, map: M) -> Result<Vec<T>, M::Error>
318 where
319 M: MapAccess<'de>,
320 {
321 let item = Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))?;
322 Ok(vec![item])
323 }
324
325 fn visit_none<E>(self) -> Result<Vec<T>, E>
326 where
327 E: de::Error,
328 {
329 Ok(vec![])
330 }
331
332 fn visit_unit<E>(self) -> Result<Vec<T>, E>
333 where
334 E: de::Error,
335 {
336 Ok(vec![])
337 }
338 }
339
340 deserializer.deserialize_any(StringOrVec(PhantomData))
341}
342
343pub fn null_or_default<'de, T, D>(deserializer: D) -> Result<T, D::Error>
348where
349 T: Deserialize<'de> + Default,
350 D: Deserializer<'de>,
351{
352 Ok(Option::<T>::deserialize(deserializer)?.unwrap_or_default())
353}
354
355#[cfg(test)]
356mod tests;
357
358pub trait Lenient {
373 fn str(&self, key: &str) -> Option<&str>;
375 fn u64(&self, key: &str) -> Option<u64>;
377 fn i64(&self, key: &str) -> Option<i64>;
379 fn f64(&self, key: &str) -> Option<f64>;
381 fn bool(&self, key: &str) -> Option<bool>;
383 fn obj(&self, key: &str) -> Option<&serde_json::Map<String, serde_json::Value>>;
385 fn arr(&self, key: &str) -> &[serde_json::Value];
387 fn at(&self, pointer: &str) -> Option<&serde_json::Value>;
389 fn as_u64_lenient(&self) -> Option<u64>;
391}
392
393impl Lenient for serde_json::Value {
394 fn str(&self, key: &str) -> Option<&str> {
395 self.get(key)?.as_str()
396 }
397
398 fn u64(&self, key: &str) -> Option<u64> {
399 self.get(key)?.as_u64_lenient()
400 }
401
402 fn i64(&self, key: &str) -> Option<i64> {
403 match self.get(key)? {
404 serde_json::Value::Number(number) => number.as_i64(),
405 serde_json::Value::String(text) => text.trim().parse().ok(),
406 _ => None,
407 }
408 }
409
410 fn f64(&self, key: &str) -> Option<f64> {
411 match self.get(key)? {
412 serde_json::Value::Number(number) => number.as_f64(),
413 serde_json::Value::String(text) => text.trim().parse().ok(),
414 _ => None,
415 }
416 }
417
418 fn bool(&self, key: &str) -> Option<bool> {
419 self.get(key)?.as_bool()
420 }
421
422 fn obj(&self, key: &str) -> Option<&serde_json::Map<String, serde_json::Value>> {
423 self.get(key)?.as_object()
424 }
425
426 fn arr(&self, key: &str) -> &[serde_json::Value] {
427 self.get(key)
428 .and_then(serde_json::Value::as_array)
429 .map_or(&[], Vec::as_slice)
430 }
431
432 fn at(&self, pointer: &str) -> Option<&serde_json::Value> {
433 self.pointer(pointer).filter(|value| !value.is_null())
434 }
435
436 fn as_u64_lenient(&self) -> Option<u64> {
437 match self {
438 serde_json::Value::Number(number) => number.as_u64().or_else(|| {
439 number
440 .as_f64()
441 .filter(|float| *float >= 0.0 && float.fract() == 0.0)
442 .map(|float| float as u64)
443 }),
444 serde_json::Value::String(text) => text.trim().parse().ok(),
445 _ => None,
446 }
447 }
448}