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}