Skip to main content

ts_wire/
value.rs

1// Copyright (c) 2026 LightSeek Foundation
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Untyped values, for fields the Python schema types as `dict` or `Any`.
22
23use bytes::Bytes;
24
25use crate::{
26    codec::Wire,
27    error::Result,
28    msgpack::{Decoder, Encoder, Integer, Kind},
29};
30
31/// Any msgpack value.
32///
33/// Maps keep their wire order, so a decoded value re-encodes to the same
34/// bytes. Integers keep the signedness of their format for the same reason.
35#[derive(Debug, Clone, PartialEq)]
36pub enum Value {
37    /// `nil`
38    Nil,
39    /// A boolean.
40    Bool(bool),
41    /// An integer.
42    Int(Integer),
43    /// A float.
44    Float(f64),
45    /// A string.
46    Str(String),
47    /// A binary value.
48    Bin(Bytes),
49    /// An array.
50    Array(Vec<Value>),
51    /// A map, in wire order.
52    Map(Vec<(Value, Value)>),
53    /// An extension value.
54    Ext(i8, Bytes),
55}
56
57impl From<&str> for Value {
58    fn from(value: &str) -> Self {
59        Value::Str(value.to_owned())
60    }
61}
62
63impl From<i64> for Value {
64    fn from(value: i64) -> Self {
65        Value::Int(if value < 0 {
66            Integer::Signed(value)
67        } else {
68            Integer::Unsigned(value as u64)
69        })
70    }
71}
72
73impl From<f64> for Value {
74    fn from(value: f64) -> Self {
75        Value::Float(value)
76    }
77}
78
79impl From<bool> for Value {
80    fn from(value: bool) -> Self {
81        Value::Bool(value)
82    }
83}
84
85impl Wire for Value {
86    fn encode(&self, encoder: &mut Encoder) {
87        match self {
88            Value::Nil => encoder.nil(),
89            Value::Bool(value) => encoder.bool(*value),
90            Value::Int(Integer::Signed(value)) => encoder.int(*value),
91            Value::Int(Integer::Unsigned(value)) => encoder.uint(*value),
92            Value::Float(value) => encoder.float(*value),
93            Value::Str(value) => encoder.str(value),
94            Value::Bin(value) => encoder.bin(value),
95            Value::Array(items) => {
96                encoder.array_len(items.len());
97                for item in items {
98                    item.encode(encoder);
99                }
100            }
101            Value::Map(entries) => {
102                encoder.map_len(entries.len());
103                for (key, value) in entries {
104                    key.encode(encoder);
105                    value.encode(encoder);
106                }
107            }
108            Value::Ext(code, data) => encoder.ext(*code, data),
109        }
110    }
111
112    fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
113        Ok(match decoder.peek_kind()? {
114            Kind::Nil => {
115                decoder.take_nil()?;
116                Value::Nil
117            }
118            Kind::Bool => Value::Bool(decoder.bool()?),
119            Kind::Int => Value::Int(decoder.integer()?),
120            Kind::Float => Value::Float(decoder.float()?),
121            Kind::Str => Value::Str(decoder.str()?.to_owned()),
122            Kind::Bin => Value::Bin(decoder.bin()?),
123            Kind::Array => {
124                let len = decoder.array_len()?;
125                let mut items = Vec::with_capacity(len.min(4096));
126                for _ in 0..len {
127                    items.push(Value::decode(decoder)?);
128                }
129                Value::Array(items)
130            }
131            Kind::Map => {
132                let len = decoder.map_len()?;
133                let mut entries = Vec::with_capacity(len.min(4096));
134                for _ in 0..len {
135                    let key = Value::decode(decoder)?;
136                    entries.push((key, Value::decode(decoder)?));
137                }
138                Value::Map(entries)
139            }
140            Kind::Ext => {
141                let (code, data) = decoder.ext()?;
142                Value::Ext(code, data)
143            }
144        })
145    }
146}