behavior_contracts/
codec.rs1use crate::value::Value;
9use serde_json::Value as J;
10
11#[derive(Debug)]
13pub struct DecodeError(pub String);
14
15impl std::fmt::Display for DecodeError {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 write!(f, "decode error: {}", self.0)
18 }
19}
20impl std::error::Error for DecodeError {}
21
22pub fn decode_value(x: &J) -> Result<Value, DecodeError> {
33 match x {
34 J::Null => Ok(Value::Null),
35 J::Bool(b) => Ok(Value::Bool(*b)),
36 J::String(s) => Ok(Value::Str(s.clone())),
37 J::Number(n) => {
38 if let Some(i) = n.as_i64() {
39 if n.is_i64() || n.is_u64() {
42 return Ok(Value::Int(i));
43 }
44 Ok(Value::Int(i))
45 } else if n.is_u64() {
46 Err(DecodeError(format!("integer {n} exceeds i64")))
47 } else {
48 let f = n
50 .as_f64()
51 .ok_or_else(|| DecodeError(format!("bad number {n}")))?;
52 Ok(Value::Float(f))
53 }
54 }
55 J::Array(a) => {
56 let mut out = Vec::with_capacity(a.len());
57 for e in a {
58 out.push(decode_value(e)?);
59 }
60 Ok(Value::Arr(out))
61 }
62 J::Object(o) => {
63 if o.len() == 1 {
64 if let Some(J::String(s)) = o.get("int") {
65 let i: i64 = s
66 .parse()
67 .map_err(|_| DecodeError(format!("int literal '{s}' not i64")))?;
68 return Ok(Value::Int(i));
69 }
70 if let Some(J::Number(n)) = o.get("float") {
71 let f = n
72 .as_f64()
73 .ok_or_else(|| DecodeError(format!("bad float {n}")))?;
74 return Ok(Value::Float(f));
75 }
76 if o.contains_key("nan") {
77 return Ok(Value::Float(f64::NAN));
78 }
79 if let Some(J::Number(n)) = o.get("inf") {
80 let sign = n.as_f64().unwrap_or(1.0);
81 return Ok(Value::Float(if sign < 0.0 {
82 f64::NEG_INFINITY
83 } else {
84 f64::INFINITY
85 }));
86 }
87 }
88 let mut out = Vec::with_capacity(o.len());
89 for (k, v) in o {
90 out.push((k.clone(), decode_value(v)?));
91 }
92 Ok(Value::Obj(out))
93 }
94 }
95}
96
97pub fn encode_value(v: &Value) -> J {
100 match v {
101 Value::Null => J::Null,
102 Value::Bool(b) => J::Bool(*b),
103 Value::Str(s) => J::String(s.clone()),
104 Value::Int(i) => {
105 const SAFE: i64 = 9_007_199_254_740_991; if *i >= -SAFE && *i <= SAFE {
107 J::Number((*i).into())
108 } else {
109 let mut m = serde_json::Map::new();
110 m.insert("int".into(), J::String(i.to_string()));
111 J::Object(m)
112 }
113 }
114 Value::Float(f) => {
115 if f.fract() == 0.0 && f.is_finite() {
116 let mut m = serde_json::Map::new();
117 m.insert(
118 "float".into(),
119 serde_json::Number::from_f64(*f)
120 .map(J::Number)
121 .unwrap_or(J::Null),
122 );
123 J::Object(m)
124 } else {
125 serde_json::Number::from_f64(*f)
126 .map(J::Number)
127 .unwrap_or(J::Null)
128 }
129 }
130 Value::Arr(a) => J::Array(a.iter().map(encode_value).collect()),
131 Value::Obj(o) => {
132 let mut m = serde_json::Map::new();
133 for (k, val) in o {
134 m.insert(k.clone(), encode_value(val));
135 }
136 J::Object(m)
137 }
138 }
139}