1use std::io;
7
8use crate::{shallow_value::ShallowValue, Encoder};
9
10use super::{
11 types::{Offset, Tag, VariantIdx},
12 Decoder, Immediate, Result,
13};
14
15#[derive(Debug, Clone, PartialEq, PartialOrd)]
17pub enum Value {
18 Null,
19 Bool(bool),
20 Int64(i64),
21 Float(f64),
22 String(String),
24 Bytes(Vec<u8>),
26 Variant0(VariantIdx),
28 Ref(Offset),
30 Pointer(Offset),
32 Tag(Tag, Box<Value>),
33 Array(Vec<Value>),
34 Map(Vec<(Value, Value)>),
35 Variant(VariantIdx, Vec<Value>),
36}
37
38impl Default for Value {
39 fn default() -> Self {
40 Value::Null
41 }
42}
43
44impl<'a> From<Immediate<'a>> for Value {
45 fn from(v: Immediate<'a>) -> Self {
46 match v {
47 Immediate::Null => Value::Null,
48 Immediate::Bool(b) => Value::Bool(b),
49 Immediate::Int64(i) => Value::Int64(i),
50 Immediate::Float(f) => Value::Float(f),
51 Immediate::String(s) => Value::String(s.to_string()),
52 Immediate::Bytes(bs) => Value::Bytes(bs.to_vec()),
53 Immediate::Variant0(variant_idx) => Value::Variant0(variant_idx),
54 Immediate::Ref(p) => Value::Ref(p),
55 Immediate::Pointer(p) => Value::Pointer(p),
56 }
57 }
58}
59
60pub fn read_value(d: &Decoder, off: Offset) -> Result<Value> {
62 let v: Value = match d.get_shallow_value(off)? {
63 ShallowValue::Imm(v) => Value::from(v),
64 ShallowValue::Tag(tag, off) => Value::Tag(tag, Box::new(read_value(d, off)?)),
65 ShallowValue::Array(arr) => {
66 let mut arr_v = Vec::with_capacity(arr.len());
67 for off in arr {
68 let off = off?;
69 arr_v.push(read_value(d, off)?)
70 }
71 Value::Array(arr_v)
72 }
73 ShallowValue::Map(map) => {
74 let mut map_v = Vec::with_capacity(map.len());
75 for kv in map {
76 let (k, v) = kv?;
77 map_v.push((read_value(d, k)?, read_value(d, v)?))
78 }
79 Value::Map(map_v)
80 }
81 ShallowValue::Variant(variant_idx, args) => {
82 let mut args_v = Vec::with_capacity(args.len());
83 for a in args {
84 let a = a?;
85 args_v.push(read_value(d, a)?)
86 }
87 Value::Variant(variant_idx, args_v)
88 }
89 };
90 Ok(v)
91}
92
93pub fn read_value_from_entrypoint(d: &Decoder) -> Result<Value> {
95 let off = d.entrypoint()?;
96 read_value(d, off)
97}
98
99fn write_value_or_imm<'a, W: io::Write>(
100 enc: &'_ mut Encoder<W>,
101 v: &'a Value,
102) -> io::Result<Immediate<'a>> {
103 let imm = match v {
104 Value::Null => Immediate::Null,
105 Value::Bool(b) => Immediate::Bool(*b),
106 Value::Int64(i) => Immediate::Int64(*i),
107 Value::Float(f) => Immediate::Float(*f),
108 Value::String(s) => Immediate::String(&s),
109 Value::Bytes(vec) => Immediate::Bytes(&vec),
110 Value::Variant0(variant_idx) => Immediate::Variant0(*variant_idx),
111 Value::Ref(p) => Immediate::Ref(*p),
112 Value::Pointer(p) => Immediate::Pointer(*p),
113 Value::Tag(tag, v) => {
114 let v = write_value_or_imm(enc, v)?;
115 enc.write_tag(*tag, v)?.into()
116 }
117 Value::Array(arr) => {
118 let mut res = Vec::with_capacity(arr.len());
120 for x in arr {
121 res.push(write_value_or_imm(enc, x)?);
122 }
123 enc.write_array(&res)?.into()
124 }
125 Value::Map(map) => {
126 let mut res = Vec::with_capacity(map.len());
128 for (k, v) in map {
129 let k = write_value_or_imm(enc, k)?;
130 let v = write_value_or_imm(enc, v)?;
131 res.push((k, v));
132 }
133 enc.write_map(&res)?.into()
134 }
135 Value::Variant(variant_idx, args) => {
136 let mut args_res = Vec::with_capacity(args.len());
137 for x in args {
138 args_res.push(write_value_or_imm(enc, x)?);
139 }
140 enc.write_variant(*variant_idx, &args_res)?.into()
141 }
142 };
143 Ok(imm)
144}
145
146pub fn write_value<'a, W: io::Write>(enc: &mut Encoder<W>, v: &Value) -> io::Result<Offset> {
148 let imm = write_value_or_imm(enc, v)?;
149 enc.write_immediate_or_return_pointer(imm)
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155 use proptest::prelude::*;
156
157 fn arb_values() -> impl Strategy<Value = Value> {
158 let leaf = prop_oneof![
160 Just(Value::Null),
161 any::<bool>().prop_map(|b| Value::Bool(b)),
162 any::<i64>().prop_map(|b| Value::Int64(b)),
163 any::<f64>().prop_map(|b| Value::Float(b)),
164 ".*".prop_map(|s| Value::String(s)),
165 prop::collection::vec(any::<u8>(), 0..100).prop_map(|v| Value::Bytes(v)),
166 ];
167 leaf.prop_recursive(8, 384, 100, |inner| {
168 prop_oneof![
169 prop::collection::vec(inner.clone(), 0..129).prop_map(|v| Value::Array(v)),
170 prop::collection::vec((inner.clone(), inner.clone()), 0..129)
171 .prop_map(|map| Value::Map(map)),
172 (any::<u64>(), inner.clone()).prop_map(|(tag, sub)| Value::Tag(tag, Box::new(sub))),
173 (any::<u32>(), prop::collection::vec(inner.clone(), 0..6))
174 .prop_map(|(c, args)| Value::Variant(VariantIdx(c), args)),
175 ]
176 })
177 .boxed()
178 }
179
180 proptest! {
181 #[test]
182 fn encode_then_decode(v in arb_values()) {
183 let mut res = vec![];
184 let mut enc= crate::Encoder::new(&mut res);
185 let offset = write_value(&mut enc, &v).unwrap();
186
187 let v2 = read_value(&Decoder::new(&res[..]).unwrap(), offset).unwrap();
188 assert_eq!(v, v2);
189 }
190 }
191}