serde_bridge/
value.rs

1use std::hash::{Hash, Hasher};
2
3use indexmap::IndexMap;
4
5/// Value is the internal represents of serde's data format.
6///
7/// Value is the one-to-one map to [serde's data format](https://serde.rs/data-model.html).
8/// Theoretically, `Value` can be converted from/to any serde format.
9///
10/// `Value` is a inter data represents which means:
11///
12/// `Value` should be constructed or consumed by `into_value` or `from_value`.
13///
14/// - `t.into_value()` -> `Value`
15/// - `into_value(t)` -> `Value`
16/// - `T::from_value(v)` -> `T`
17/// - `from_value(v)` -> `T`
18///
19/// `Value` also implements [`serde::Serialize`](https://docs.serde.rs/serde/trait.Serialize.html) and [`serde::Deserialize`](https://docs.serde.rs/serde/trait.Deserialize.html).
20/// `Serialize` and `Deserialize` on `Value` that converted from `T` will be the same with `T`.
21///
22/// # Examples
23///
24/// ## Conversion between `T` and `Value`
25///
26/// ```
27/// use anyhow::Result;
28/// use serde_bridge::{from_value, into_value, FromValue, IntoValue, Value};
29///
30/// fn main() -> Result<()> {
31///     let v = bool::from_value(Value::Bool(true))?;
32///     assert!(v);
33///
34///     let v: bool = from_value(Value::Bool(true))?;
35///     assert!(v);
36///
37///     let v = true.into_value()?;
38///     assert_eq!(v, Value::Bool(true));
39///
40///     let v = into_value(true)?;
41///     assert_eq!(v, Value::Bool(true));
42///
43///     Ok(())
44/// }
45/// ```
46///
47/// ## Transparent Serialize and Deserialize
48///
49/// ```
50/// use anyhow::Result;
51/// use serde_bridge::{from_value, into_value, FromValue, IntoValue, Value};
52/// use serde_json;
53///
54/// fn main() -> Result<()> {
55///     let raw = serde_json::to_string(&true)?;
56///     let value = serde_json::to_string(&true.into_value()?)?;
57///     assert_eq!(raw, value);
58///
59///     let raw: bool = serde_json::from_str("true")?;
60///     let value: Value = serde_json::from_str("true")?;
61///     assert_eq!(raw, bool::from_value(value)?);
62///
63///     Ok(())
64/// }
65/// ```
66#[derive(Debug, Clone, PartialEq)]
67pub enum Value {
68    /// primitive types for `bool`: `false`/`true`
69    Bool(bool),
70    /// primitive types for `i8`
71    I8(i8),
72    /// primitive types for `i16`
73    I16(i16),
74    /// primitive types for `i32`
75    I32(i32),
76    /// primitive types for `i64`
77    I64(i64),
78    /// primitive types for `i128`
79    I128(i128),
80    /// primitive types for `u8`
81    U8(u8),
82    /// primitive types for `u16`
83    U16(u16),
84    /// primitive types for `u32`
85    U32(u32),
86    /// primitive types for `u64`
87    U64(u64),
88    /// primitive types for `u128`
89    U128(u128),
90    /// primitive types for `f32`
91    F32(f32),
92    /// primitive types for `f64`
93    F64(f64),
94    /// primitive types for `char`
95    Char(char),
96    /// string type
97    ///
98    /// UTF-8 bytes with a length and no null terminator. May contain 0-bytes.
99    Str(String),
100    /// byte array
101    ///
102    /// Similar to strings, during deserialization byte arrays can be transient, owned, or borrowed.
103    Bytes(Vec<u8>),
104    /// `None` part of an `Option`
105    None,
106    /// `Some` part of an `Option`
107    ///
108    /// # Note
109    ///
110    /// We use `Box` here to workaround recursive data type.
111    Some(Box<Value>),
112    /// The type of `()` in Rust.
113    ///
114    /// It represents an anonymous value containing no data.
115    Unit,
116    /// For example `struct Unit` or `PhantomData<T>`.
117    ///
118    /// It represents a named value containing no data.
119    UnitStruct(&'static str),
120    /// For example the `E::A` and `E::B` in `enum E { A, B }`.
121    UnitVariant {
122        name: &'static str,
123        variant_index: u32,
124        variant: &'static str,
125    },
126    /// For example struct `Millimeters(u8)`.
127    NewtypeStruct(&'static str, Box<Value>),
128    /// For example the `E::N` in `enum E { N(u8) }`.
129    ///
130    /// # Note
131    ///
132    /// We use `Box` here to workaround recursive data type.
133    NewtypeVariant {
134        name: &'static str,
135        variant_index: u32,
136        variant: &'static str,
137        value: Box<Value>,
138    },
139    /// A variably sized heterogeneous sequence of values, for example `Vec<T>` or `HashSet<T>`
140    Seq(Vec<Value>),
141    /// A statically sized heterogeneous sequence of values for which the length will be known at deserialization time without looking at the serialized data.
142    ///
143    /// For example `(u8,)` or `(String, u64, Vec<T>)` or `[u64; 10]`.
144    Tuple(Vec<Value>),
145    /// A named tuple, for example `struct Rgb(u8, u8, u8)`.
146    TupleStruct(&'static str, Vec<Value>),
147    /// For example the `E::T` in `enum E { T(u8, u8) }`.
148    TupleVariant {
149        name: &'static str,
150        variant_index: u32,
151        variant: &'static str,
152        fields: Vec<Value>,
153    },
154    /// A variably sized heterogeneous key-value pairing, for example `BTreeMap<K, V>`
155    Map(IndexMap<Value, Value>),
156    /// A statically sized heterogeneous key-value pairing in which the keys are compile-time
157    /// constant strings and will be known at deserialization time without looking at the
158    /// serialized data.
159    ///
160    /// For example `struct S { r: u8, g: u8, b: u8 }`.
161    Struct(&'static str, IndexMap<&'static str, Value>),
162    /// For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`.
163    StructVariant {
164        name: &'static str,
165        variant_index: u32,
166        variant: &'static str,
167        fields: IndexMap<&'static str, Value>,
168    },
169}
170
171impl Eq for Value {}
172
173/// Implement Hash for Value so that we can use value as hash key.
174///
175/// ## Notes
176///
177/// Not all variants supports hash.
178///
179/// ## FIXME
180///
181/// does this implementation correct?
182#[allow(clippy::derived_hash_with_manual_eq)]
183impl Hash for Value {
184    fn hash<H: Hasher>(&self, state: &mut H) {
185        // Write current enum discriminant into state.
186        std::mem::discriminant(self).hash(state);
187        match self {
188            Value::Bool(v) => v.hash(state),
189            Value::I8(v) => v.hash(state),
190            Value::I16(v) => v.hash(state),
191            Value::I32(v) => v.hash(state),
192            Value::I64(v) => v.hash(state),
193            Value::I128(v) => v.hash(state),
194            Value::U8(v) => v.hash(state),
195            Value::U16(v) => v.hash(state),
196            Value::U32(v) => v.hash(state),
197            Value::U64(v) => v.hash(state),
198            Value::U128(v) => v.hash(state),
199            Value::F32(_) => panic!("f32 is not hashable"),
200            Value::F64(_) => panic!("f64 is not hashable"),
201            Value::Char(v) => v.hash(state),
202            Value::Str(v) => v.hash(state),
203            Value::Bytes(v) => v.hash(state),
204            Value::None => {}
205            Value::Some(v) => v.hash(state),
206            Value::Unit => {}
207            Value::UnitStruct(v) => v.hash(state),
208            Value::UnitVariant {
209                name,
210                variant_index,
211                variant,
212            } => {
213                name.hash(state);
214                variant_index.hash(state);
215                variant.hash(state);
216            }
217            Value::NewtypeStruct(name, value) => {
218                name.hash(state);
219                value.hash(state);
220            }
221            Value::NewtypeVariant {
222                name,
223                variant_index,
224                variant,
225                value,
226            } => {
227                name.hash(state);
228                variant_index.hash(state);
229                variant.hash(state);
230                value.hash(state);
231            }
232            Value::Seq(v) => v.hash(state),
233            Value::Tuple(v) => v.hash(state),
234            Value::TupleStruct(name, fields) => {
235                name.hash(state);
236                fields.hash(state);
237            }
238            Value::TupleVariant {
239                name,
240                variant_index,
241                variant,
242                fields,
243            } => {
244                name.hash(state);
245                variant_index.hash(state);
246                variant.hash(state);
247                fields.hash(state);
248            }
249            Value::Map(v) => {
250                for e in v {
251                    e.hash(state)
252                }
253            }
254            Value::Struct(name, fields) => {
255                name.hash(state);
256                for e in fields {
257                    e.hash(state)
258                }
259            }
260            Value::StructVariant {
261                name,
262                variant_index,
263                variant,
264                fields,
265            } => {
266                name.hash(state);
267                variant_index.hash(state);
268                variant.hash(state);
269                for e in fields {
270                    e.hash(state)
271                }
272            }
273        }
274    }
275}
276
277#[cfg(test)]
278mod tests {
279    use super::*;
280
281    #[test]
282    fn test_enum_size() {
283        println!("Size is {}", std::mem::size_of::<Value>());
284    }
285}