Skip to main content

template/
value.rs

1//! Dynamic value type used during template rendering, with serde serialization support.
2
3use std::{collections::BTreeMap, fmt, rc::Rc};
4
5use serde::ser::{self, Serialize, Serializer};
6
7/// A dynamic value used during template rendering.
8///
9/// Supports strings, numbers, booleans, null, arrays, maps, and
10/// `Safe` strings that bypass auto-escaping.
11#[derive(Clone, Debug, PartialEq)]
12pub enum Value {
13    Null,
14    Bool(bool),
15    I64(i64),
16    F64(f64),
17    /// A string value. Will be auto-escaped in `Mode::Html`.
18    Str(Rc<str>),
19    /// A string that is already safe for output. Bypasses auto-escaping.
20    /// Returned by `{{ value | safe }}`, the `escape` filter, and `{{ super() }}`.
21    Safe(Rc<str>),
22    Array(Rc<Vec<Value>>),
23    Map(Rc<BTreeMap<String, Value>>),
24}
25
26/// Error returned when serializing a value fails.
27#[derive(Debug)]
28pub struct SerdeError(pub String);
29
30impl fmt::Display for SerdeError {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        write!(f, "{}", self.0)
33    }
34}
35
36impl std::error::Error for SerdeError {}
37
38impl ser::Error for SerdeError {
39    fn custom<T: fmt::Display>(msg: T) -> Self {
40        SerdeError(msg.to_string())
41    }
42}
43
44impl Value {
45    fn from_serialize_impl<S: Serialize>(value: &S) -> Result<Self, SerdeError> {
46        let serializer = ValueSerializer;
47        value.serialize(serializer)
48    }
49
50    /// Returns `true` if the value is considered truthy.
51    ///
52    /// Falsy values are: `Null`, `false`, `0`, `0.0`, empty string, empty array, empty map.
53    pub fn is_truthy(&self) -> bool {
54        match self {
55            Value::Null => false,
56            Value::Bool(b) => *b,
57            Value::I64(n) => *n != 0,
58            Value::F64(n) => *n != 0.0 && !n.is_nan(),
59            Value::Str(s) | Value::Safe(s) => !s.is_empty(),
60            Value::Array(a) => !a.is_empty(),
61            Value::Map(m) => !m.is_empty(),
62        }
63    }
64
65    /// Look up a key in a map value. Returns `None` if not a map or key missing.
66    pub fn get(&self, key: &str) -> Option<Value> {
67        match self {
68            Value::Map(m) => m.get(key).cloned(),
69            _ => None,
70        }
71    }
72
73    /// Look up an index in an array value. Returns `None` if not an array or index out of bounds.
74    pub fn get_index(&self, index: usize) -> Option<Value> {
75        match self {
76            Value::Array(a) => a.get(index).cloned(),
77            _ => None,
78        }
79    }
80
81    /// Return the string content if this is a `Str` or `Safe` value.
82    pub fn as_str(&self) -> Option<&str> {
83        match self {
84            Value::Str(s) => Some(s),
85            Value::Safe(s) => Some(s),
86            _ => None,
87        }
88    }
89
90    /// Format the value into the given buffer.
91    ///
92    /// Arrays and maps render as `[Array]` / `[Object]` placeholders.
93    pub fn fmt_to(&self, buf: &mut impl fmt::Write) -> fmt::Result {
94        match self {
95            Value::Null => Ok(()),
96            Value::Bool(b) => write!(buf, "{b}"),
97            Value::I64(n) => write!(buf, "{n}"),
98            Value::F64(n) => write!(buf, "{n}"),
99            Value::Str(s) | Value::Safe(s) => buf.write_str(s),
100            Value::Array(_) => write!(buf, "[Array]"),
101            Value::Map(_) => write!(buf, "[Object]"),
102        }
103    }
104}
105
106impl Serialize for Value {
107    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
108        match self {
109            Value::Null => serializer.serialize_unit(),
110            Value::Bool(b) => serializer.serialize_bool(*b),
111            Value::I64(n) => serializer.serialize_i64(*n),
112            Value::F64(n) => serializer.serialize_f64(*n),
113            Value::Str(s) | Value::Safe(s) => serializer.serialize_str(s),
114            Value::Array(a) => {
115                use serde::ser::SerializeSeq;
116                let mut seq = serializer.serialize_seq(Some(a.len()))?;
117                for v in a.iter() {
118                    seq.serialize_element(v)?;
119                }
120                seq.end()
121            }
122            Value::Map(m) => {
123                use serde::ser::SerializeMap;
124                let mut map = serializer.serialize_map(Some(m.len()))?;
125                for (k, v) in m.iter() {
126                    map.serialize_entry(k, v)?;
127                }
128                map.end()
129            }
130        }
131    }
132}
133
134struct ValueSerializer;
135
136impl Serializer for ValueSerializer {
137    type Ok = Value;
138    type Error = SerdeError;
139
140    type SerializeSeq = ValueSeqSerializer;
141    type SerializeTuple = ValueSeqSerializer;
142    type SerializeTupleStruct = ValueSeqSerializer;
143    type SerializeTupleVariant = ValueSeqSerializer;
144    type SerializeMap = ValueMapSerializer;
145    type SerializeStruct = ValueMapSerializer;
146    type SerializeStructVariant = ValueMapSerializer;
147
148    fn serialize_bool(self, v: bool) -> Result<Value, SerdeError> {
149        Ok(Value::Bool(v))
150    }
151
152    fn serialize_i8(self, v: i8) -> Result<Value, SerdeError> {
153        Ok(Value::I64(v as i64))
154    }
155
156    fn serialize_i16(self, v: i16) -> Result<Value, SerdeError> {
157        Ok(Value::I64(v as i64))
158    }
159
160    fn serialize_i32(self, v: i32) -> Result<Value, SerdeError> {
161        Ok(Value::I64(v as i64))
162    }
163
164    fn serialize_i64(self, v: i64) -> Result<Value, SerdeError> {
165        Ok(Value::I64(v))
166    }
167
168    fn serialize_u8(self, v: u8) -> Result<Value, SerdeError> {
169        Ok(Value::I64(v as i64))
170    }
171
172    fn serialize_u16(self, v: u16) -> Result<Value, SerdeError> {
173        Ok(Value::I64(v as i64))
174    }
175
176    fn serialize_u32(self, v: u32) -> Result<Value, SerdeError> {
177        Ok(Value::I64(v as i64))
178    }
179
180    fn serialize_u64(self, v: u64) -> Result<Value, SerdeError> {
181        if v <= i64::MAX as u64 {
182            Ok(Value::I64(v as i64))
183        } else {
184            Ok(Value::F64(v as f64))
185        }
186    }
187
188    fn serialize_f32(self, v: f32) -> Result<Value, SerdeError> {
189        Ok(Value::F64(v as f64))
190    }
191
192    fn serialize_f64(self, v: f64) -> Result<Value, SerdeError> {
193        Ok(Value::F64(v))
194    }
195
196    fn serialize_char(self, v: char) -> Result<Value, SerdeError> {
197        let mut s = String::with_capacity(1);
198        s.push(v);
199        Ok(Value::Str(s.into()))
200    }
201
202    fn serialize_str(self, v: &str) -> Result<Value, SerdeError> {
203        Ok(Value::Str(v.into()))
204    }
205
206    fn serialize_bytes(self, _v: &[u8]) -> Result<Value, SerdeError> {
207        Err(SerdeError("bytes not supported".into()))
208    }
209
210    fn serialize_none(self) -> Result<Value, SerdeError> {
211        Ok(Value::Null)
212    }
213
214    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Value, SerdeError>
215    where
216        T: Serialize,
217    {
218        value.serialize(self)
219    }
220
221    fn serialize_unit(self) -> Result<Value, SerdeError> {
222        Ok(Value::Null)
223    }
224
225    fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, SerdeError> {
226        Ok(Value::Null)
227    }
228
229    fn serialize_unit_variant(
230        self,
231        _name: &'static str,
232        _variant_index: u32,
233        variant: &'static str,
234    ) -> Result<Value, SerdeError> {
235        Ok(Value::Str(variant.into()))
236    }
237
238    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> Result<Value, SerdeError>
239    where
240        T: Serialize,
241    {
242        value.serialize(self)
243    }
244
245    fn serialize_newtype_variant<T: ?Sized>(
246        self,
247        _name: &'static str,
248        _variant_index: u32,
249        _variant: &'static str,
250        value: &T,
251    ) -> Result<Value, SerdeError>
252    where
253        T: Serialize,
254    {
255        value.serialize(self)
256    }
257
258    fn serialize_seq(self, _len: Option<usize>) -> Result<ValueSeqSerializer, SerdeError> {
259        Ok(ValueSeqSerializer(Vec::new()))
260    }
261
262    fn serialize_tuple(self, len: usize) -> Result<ValueSeqSerializer, SerdeError> {
263        self.serialize_seq(Some(len))
264    }
265
266    fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<ValueSeqSerializer, SerdeError> {
267        self.serialize_seq(Some(len))
268    }
269
270    fn serialize_tuple_variant(
271        self,
272        _name: &'static str,
273        _variant_index: u32,
274        _variant: &'static str,
275        len: usize,
276    ) -> Result<ValueSeqSerializer, SerdeError> {
277        self.serialize_seq(Some(len))
278    }
279
280    fn serialize_map(self, _len: Option<usize>) -> Result<ValueMapSerializer, SerdeError> {
281        Ok(ValueMapSerializer(BTreeMap::new(), None))
282    }
283
284    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<ValueMapSerializer, SerdeError> {
285        self.serialize_map(Some(len))
286    }
287
288    fn serialize_struct_variant(
289        self,
290        _name: &'static str,
291        _variant_index: u32,
292        _variant: &'static str,
293        len: usize,
294    ) -> Result<ValueMapSerializer, SerdeError> {
295        self.serialize_map(Some(len))
296    }
297}
298
299struct ValueSeqSerializer(Vec<Value>);
300
301impl ser::SerializeSeq for ValueSeqSerializer {
302    type Ok = Value;
303    type Error = SerdeError;
304
305    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), SerdeError>
306    where
307        T: Serialize,
308    {
309        self.0.push(value.serialize(ValueSerializer)?);
310        Ok(())
311    }
312
313    fn end(self) -> Result<Value, SerdeError> {
314        Ok(Value::Array(Rc::new(self.0)))
315    }
316}
317
318impl ser::SerializeTuple for ValueSeqSerializer {
319    type Ok = Value;
320    type Error = SerdeError;
321
322    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), SerdeError>
323    where
324        T: Serialize,
325    {
326        ser::SerializeSeq::serialize_element(self, value)
327    }
328
329    fn end(self) -> Result<Value, SerdeError> {
330        ser::SerializeSeq::end(self)
331    }
332}
333
334impl ser::SerializeTupleStruct for ValueSeqSerializer {
335    type Ok = Value;
336    type Error = SerdeError;
337
338    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), SerdeError>
339    where
340        T: Serialize,
341    {
342        ser::SerializeSeq::serialize_element(self, value)
343    }
344
345    fn end(self) -> Result<Value, SerdeError> {
346        ser::SerializeSeq::end(self)
347    }
348}
349
350impl ser::SerializeTupleVariant for ValueSeqSerializer {
351    type Ok = Value;
352    type Error = SerdeError;
353
354    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), SerdeError>
355    where
356        T: Serialize,
357    {
358        ser::SerializeSeq::serialize_element(self, value)
359    }
360
361    fn end(self) -> Result<Value, SerdeError> {
362        ser::SerializeSeq::end(self)
363    }
364}
365
366struct ValueMapSerializer(BTreeMap<String, Value>, Option<String>);
367
368impl ser::SerializeMap for ValueMapSerializer {
369    type Ok = Value;
370    type Error = SerdeError;
371
372    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), SerdeError>
373    where
374        T: Serialize,
375    {
376        let k = key.serialize(MapKeySerializer)?;
377        self.1 = Some(k);
378        Ok(())
379    }
380
381    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), SerdeError>
382    where
383        T: Serialize,
384    {
385        let key = self
386            .1
387            .take()
388            .ok_or_else(|| SerdeError("serialize_value called without serialize_key".into()))?;
389        let v = value.serialize(ValueSerializer)?;
390        self.0.insert(key, v);
391        Ok(())
392    }
393
394    fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<(), SerdeError>
395    where
396        K: Serialize,
397        V: Serialize,
398    {
399        let k = key.serialize(MapKeySerializer)?;
400        let v = value.serialize(ValueSerializer)?;
401        self.0.insert(k, v);
402        Ok(())
403    }
404
405    fn end(self) -> Result<Value, SerdeError> {
406        Ok(Value::Map(Rc::new(self.0)))
407    }
408}
409
410impl ser::SerializeStruct for ValueMapSerializer {
411    type Ok = Value;
412    type Error = SerdeError;
413
414    fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), SerdeError>
415    where
416        T: Serialize,
417    {
418        let v = value.serialize(ValueSerializer)?;
419        self.0.insert(key.to_string(), v);
420        Ok(())
421    }
422
423    fn end(self) -> Result<Value, SerdeError> {
424        Ok(Value::Map(Rc::new(self.0)))
425    }
426}
427
428impl ser::SerializeStructVariant for ValueMapSerializer {
429    type Ok = Value;
430    type Error = SerdeError;
431
432    fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), SerdeError>
433    where
434        T: Serialize,
435    {
436        ser::SerializeStruct::serialize_field(self, key, value)
437    }
438
439    fn end(self) -> Result<Value, SerdeError> {
440        ser::SerializeStruct::end(self)
441    }
442}
443
444struct MapKeySerializer;
445
446impl Serializer for MapKeySerializer {
447    type Ok = String;
448    type Error = SerdeError;
449
450    type SerializeSeq = ser::Impossible<String, SerdeError>;
451    type SerializeTuple = ser::Impossible<String, SerdeError>;
452    type SerializeTupleStruct = ser::Impossible<String, SerdeError>;
453    type SerializeTupleVariant = ser::Impossible<String, SerdeError>;
454    type SerializeMap = ser::Impossible<String, SerdeError>;
455    type SerializeStruct = ser::Impossible<String, SerdeError>;
456    type SerializeStructVariant = ser::Impossible<String, SerdeError>;
457
458    fn serialize_bool(self, v: bool) -> Result<String, SerdeError> {
459        Ok(v.to_string())
460    }
461    fn serialize_i8(self, v: i8) -> Result<String, SerdeError> {
462        Ok(v.to_string())
463    }
464    fn serialize_i16(self, v: i16) -> Result<String, SerdeError> {
465        Ok(v.to_string())
466    }
467    fn serialize_i32(self, v: i32) -> Result<String, SerdeError> {
468        Ok(v.to_string())
469    }
470    fn serialize_i64(self, v: i64) -> Result<String, SerdeError> {
471        Ok(v.to_string())
472    }
473    fn serialize_u8(self, v: u8) -> Result<String, SerdeError> {
474        Ok(v.to_string())
475    }
476    fn serialize_u16(self, v: u16) -> Result<String, SerdeError> {
477        Ok(v.to_string())
478    }
479    fn serialize_u32(self, v: u32) -> Result<String, SerdeError> {
480        Ok(v.to_string())
481    }
482    fn serialize_u64(self, v: u64) -> Result<String, SerdeError> {
483        Ok(v.to_string())
484    }
485    fn serialize_f32(self, v: f32) -> Result<String, SerdeError> {
486        Ok(v.to_string())
487    }
488    fn serialize_f64(self, v: f64) -> Result<String, SerdeError> {
489        Ok(v.to_string())
490    }
491    fn serialize_char(self, v: char) -> Result<String, SerdeError> {
492        let mut s = String::with_capacity(1);
493        s.push(v);
494        Ok(s)
495    }
496    fn serialize_str(self, v: &str) -> Result<String, SerdeError> {
497        Ok(v.to_string())
498    }
499    fn serialize_bytes(self, _v: &[u8]) -> Result<String, SerdeError> {
500        Err(SerdeError("bytes not supported as map key".into()))
501    }
502    fn serialize_none(self) -> Result<String, SerdeError> {
503        Err(SerdeError("none not supported as map key".into()))
504    }
505    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<String, SerdeError>
506    where
507        T: Serialize,
508    {
509        Err(SerdeError("some not supported as map key".into()))
510    }
511    fn serialize_unit(self) -> Result<String, SerdeError> {
512        Ok(String::new())
513    }
514    fn serialize_unit_struct(self, _name: &'static str) -> Result<String, SerdeError> {
515        Ok(String::new())
516    }
517    fn serialize_unit_variant(
518        self,
519        _name: &'static str,
520        _variant_index: u32,
521        variant: &'static str,
522    ) -> Result<String, SerdeError> {
523        Ok(variant.to_string())
524    }
525    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T) -> Result<String, SerdeError> {
526        Err(SerdeError("newtype struct not supported as map key".into()))
527    }
528    fn serialize_newtype_variant<T: ?Sized>(
529        self,
530        _name: &'static str,
531        _variant_index: u32,
532        _variant: &'static str,
533        _value: &T,
534    ) -> Result<String, SerdeError> {
535        Err(SerdeError("newtype variant not supported as map key".into()))
536    }
537    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, SerdeError> {
538        Err(SerdeError("sequence not supported as map key".into()))
539    }
540    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, SerdeError> {
541        Err(SerdeError("tuple not supported as map key".into()))
542    }
543    fn serialize_tuple_struct(
544        self,
545        _name: &'static str,
546        _len: usize,
547    ) -> Result<Self::SerializeTupleStruct, SerdeError> {
548        Err(SerdeError("tuple struct not supported as map key".into()))
549    }
550    fn serialize_tuple_variant(
551        self,
552        _name: &'static str,
553        _variant_index: u32,
554        _variant: &'static str,
555        _len: usize,
556    ) -> Result<Self::SerializeTupleVariant, SerdeError> {
557        Err(SerdeError("tuple variant not supported as map key".into()))
558    }
559    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, SerdeError> {
560        Err(SerdeError("map not supported as map key".into()))
561    }
562    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct, SerdeError> {
563        Err(SerdeError("struct not supported as map key".into()))
564    }
565    fn serialize_struct_variant(
566        self,
567        _name: &'static str,
568        _variant_index: u32,
569        _variant: &'static str,
570        _len: usize,
571    ) -> Result<Self::SerializeStructVariant, SerdeError> {
572        Err(SerdeError("struct variant not supported as map key".into()))
573    }
574}
575
576macro_rules! from_value {
577    ($($ty:ty => $variant:ident),* $(,)?) => {
578        $(
579            impl From<$ty> for Value {
580                fn from(v: $ty) -> Self {
581                    Value::$variant(v)
582                }
583            }
584        )*
585    };
586}
587
588from_value! {
589    bool => Bool,
590    i64 => I64,
591    f64 => F64,
592}
593
594impl From<&str> for Value {
595    fn from(s: &str) -> Self {
596        Value::Str(s.into())
597    }
598}
599
600impl From<String> for Value {
601    fn from(s: String) -> Self {
602        Value::Str(s.into())
603    }
604}
605
606impl From<i32> for Value {
607    fn from(v: i32) -> Self {
608        Value::I64(v as i64)
609    }
610}
611
612impl From<usize> for Value {
613    fn from(v: usize) -> Self {
614        if v <= i64::MAX as usize {
615            Value::I64(v as i64)
616        } else {
617            Value::F64(v as f64)
618        }
619    }
620}
621
622impl<T: Into<Value>> From<Vec<T>> for Value {
623    fn from(v: Vec<T>) -> Self {
624        Value::Array(Rc::new(v.into_iter().map(Into::into).collect()))
625    }
626}
627
628impl<T: Into<Value>> From<BTreeMap<String, T>> for Value {
629    fn from(v: BTreeMap<String, T>) -> Self {
630        Value::Map(Rc::new(v.into_iter().map(|(k, v)| (k, v.into())).collect()))
631    }
632}
633
634impl From<Value> for String {
635    fn from(v: Value) -> Self {
636        let mut buf = String::new();
637        v.fmt_to(&mut buf).unwrap();
638        buf
639    }
640}
641
642impl fmt::Display for Value {
643    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
644        self.fmt_to(f)
645    }
646}
647
648/// Convert a `Serialize` value into a `Value` for template rendering.
649///
650/// Supports all standard Rust types and any `#[derive(Serialize)]` struct/enum.
651/// `u64` values larger than `i64::MAX` are stored as `F64`.
652pub fn to_value<S: Serialize>(value: S) -> Result<Value, SerdeError> {
653    Value::from_serialize_impl(&value)
654}
655
656#[cfg(test)]
657mod tests {
658    use std::collections::BTreeMap;
659
660    use super::*;
661
662    #[test]
663    fn test_basic_types() {
664        assert_eq!(to_value(42i64).unwrap(), Value::I64(42));
665        assert_eq!(to_value(true).unwrap(), Value::Bool(true));
666        assert_eq!(to_value("hello").unwrap(), Value::Str("hello".into()));
667        assert_eq!(to_value(false).unwrap(), Value::Bool(false));
668    }
669
670    #[test]
671    fn test_option() {
672        let some_val: Option<i64> = Some(42);
673        assert_eq!(to_value(some_val).unwrap(), Value::I64(42));
674        let none_val: Option<i64> = None;
675        assert_eq!(to_value(none_val).unwrap(), Value::Null);
676    }
677
678    #[test]
679    fn test_vec() {
680        let v = vec![1, 2, 3];
681        let val = to_value(v).unwrap();
682        match val {
683            Value::Array(ref arr) => {
684                assert_eq!(arr.len(), 3);
685                assert_eq!(arr[0], Value::I64(1));
686            }
687            _ => panic!("expected array"),
688        }
689    }
690
691    #[test]
692    fn test_map() {
693        let mut map = BTreeMap::new();
694        map.insert("name".to_string(), "Alice".to_string());
695        let val = to_value(map).unwrap();
696        match val {
697            Value::Map(ref m) => {
698                assert_eq!(m.get("name"), Some(&Value::Str("Alice".into())));
699            }
700            _ => panic!("expected map"),
701        }
702    }
703
704    #[test]
705    fn test_struct() {
706        let user = BTreeMap::from([
707            ("name".to_string(), Value::Str("Bob".into())),
708            ("age".to_string(), Value::I64(30)),
709        ]);
710        let val = Value::Map(Rc::new(user));
711        match val {
712            Value::Map(ref m) => {
713                assert_eq!(m.get("name"), Some(&Value::Str("Bob".into())));
714                assert_eq!(m.get("age"), Some(&Value::I64(30)));
715            }
716            _ => panic!("expected map"),
717        }
718    }
719
720    #[test]
721    fn test_truthy() {
722        assert!(!Value::Null.is_truthy());
723        assert!(!Value::Bool(false).is_truthy());
724        assert!(!Value::I64(0).is_truthy());
725        assert!(!Value::F64(0.0).is_truthy());
726        assert!(!Value::Str("".into()).is_truthy());
727        assert!(!Value::Array(Rc::new(vec![])).is_truthy());
728        assert!(!Value::Map(Rc::new(BTreeMap::new())).is_truthy());
729        assert!(Value::Bool(true).is_truthy());
730        assert!(Value::I64(1).is_truthy());
731        assert!(Value::Str("x".into()).is_truthy());
732    }
733
734    #[test]
735    fn test_get() {
736        let mut map = BTreeMap::new();
737        map.insert("key".to_string(), Value::I64(42));
738        let val = Value::Map(Rc::new(map));
739        assert_eq!(val.get("key"), Some(Value::I64(42)));
740        assert_eq!(val.get("nonexistent"), None);
741    }
742
743    #[test]
744    fn test_u64_overflow() {
745        // u64::MAX overflows i64, should serialize to f64
746        let val = to_value(u64::MAX).unwrap();
747        assert!(matches!(val, Value::F64(_)));
748    }
749
750    #[test]
751    fn test_large_u64_as_i64() {
752        // i64::MAX as u64 should still be I64
753        let val = to_value(i64::MAX as u64).unwrap();
754        assert_eq!(val, Value::I64(i64::MAX));
755    }
756
757    #[test]
758    fn test_safe_variant_truthy() {
759        assert!(Value::Safe("x".into()).is_truthy());
760        assert!(!Value::Safe("".into()).is_truthy());
761    }
762
763    #[test]
764    fn test_safe_variant_as_str() {
765        let val = Value::Safe("hello".into());
766        assert_eq!(val.as_str(), Some("hello"));
767    }
768
769    #[test]
770    fn test_safe_variant_fmt() {
771        let val = Value::Safe("hello".into());
772        let mut buf = String::new();
773        val.fmt_to(&mut buf).unwrap();
774        assert_eq!(buf, "hello");
775    }
776
777    #[test]
778    fn test_nan_truthy() {
779        let val = Value::F64(f64::NAN);
780        assert!(!val.is_truthy());
781    }
782
783    #[test]
784    fn test_infinity_truthy() {
785        let val = Value::F64(f64::INFINITY);
786        assert!(val.is_truthy());
787    }
788
789    #[test]
790    fn test_neg_infinity_truthy() {
791        let val = Value::F64(f64::NEG_INFINITY);
792        assert!(val.is_truthy());
793    }
794
795    #[test]
796    fn test_f64_neg_zero_truthy() {
797        let val = Value::F64(-0.0);
798        assert!(!val.is_truthy());
799    }
800
801    #[test]
802    fn test_get_on_non_map() {
803        let val = Value::I64(42);
804        assert_eq!(val.get("key"), None);
805    }
806
807    #[test]
808    fn test_get_index_on_non_array() {
809        let val = Value::I64(42);
810        assert_eq!(val.get_index(0), None);
811    }
812
813    #[test]
814    fn test_get_index_out_of_bounds() {
815        let val = Value::Array(Rc::new(vec![Value::I64(1)]));
816        assert_eq!(val.get_index(5), None);
817    }
818
819    #[test]
820    fn test_as_str_on_non_string() {
821        let val = Value::I64(42);
822        assert_eq!(val.as_str(), None);
823    }
824
825    #[test]
826    fn test_fmt_to_null() {
827        let val = Value::Null;
828        let mut buf = String::new();
829        val.fmt_to(&mut buf).unwrap();
830        assert_eq!(buf, "");
831    }
832
833    #[test]
834    fn test_fmt_to_array() {
835        let val = Value::Array(Rc::new(vec![Value::I64(1)]));
836        let mut buf = String::new();
837        val.fmt_to(&mut buf).unwrap();
838        assert_eq!(buf, "[Array]");
839    }
840
841    #[test]
842    fn test_fmt_to_map() {
843        let mut m = BTreeMap::new();
844        m.insert("k".to_string(), Value::I64(1));
845        let val = Value::Map(Rc::new(m));
846        let mut buf = String::new();
847        val.fmt_to(&mut buf).unwrap();
848        assert_eq!(buf, "[Object]");
849    }
850}