mbon/
data.rs

1//! Internal data structs
2//!
3//! Here, you'll find [Value], [Mark], and [Type].
4
5use std::fmt::Display;
6
7use serde::{Deserialize, Serialize};
8
9use crate::{
10    error::{Error, Result},
11    object::{ObjectDump, ObjectParse},
12};
13
14use self::{de::ValueDe, ser::ValueSer};
15
16pub mod de;
17pub mod ser;
18
19/// The basic unit for data in binary save data.
20///
21/// This is used as an intermidiate object for dumping/loading binary data. You
22/// will generally not need to use this struct.
23#[derive(Debug, Clone, PartialEq)]
24pub enum Value {
25    Long(i64),
26    Int(i32),
27    Short(i16),
28    Char(i8),
29    Float(f32),
30    Double(f64),
31    Bytes(Vec<u8>),
32    Str(String),
33    Object(Vec<u8>),
34    Enum(u32, Box<Value>),
35    Null,
36    List(Vec<Value>),
37    Map(Vec<(Value, Value)>),
38}
39
40impl Value {
41    /// Get the type of this value.
42    ///
43    /// This will return the actual type that would be stored when the value is
44    /// converted into binary.
45    ///
46    /// ```
47    /// use mbon::data::{Value, Type};
48    ///
49    /// assert_eq!(Value::Long(32).get_type(), Type::Long);
50    ///
51    /// assert_eq!(
52    ///     Value::List(vec![Value::Int(64), Value::Int(12)]).get_type(),
53    ///     Type::Array
54    /// );
55    ///
56    /// assert_eq!(
57    ///     Value::List(vec![Value::Int(64), Value::Short(12)]).get_type(),
58    ///     Type::List
59    /// );
60    /// ```
61    pub fn get_type(&self) -> Type {
62        match self {
63            Value::Long(_) => Type::Long,
64            Value::Int(_) => Type::Int,
65            Value::Short(_) => Type::Short,
66            Value::Char(_) => Type::Char,
67            Value::Float(_) => Type::Float,
68            Value::Double(_) => Type::Double,
69            Value::Bytes(_) => Type::Bytes,
70            Value::Str(_) => Type::Str,
71            Value::Object(_) => Type::Object,
72            Value::Enum(_, _) => Type::Enum,
73            Value::Null => Type::Null,
74            Value::List(v) => {
75                if Self::can_be_array(v) {
76                    Type::Array
77                } else {
78                    Type::List
79                }
80            }
81            Value::Map(v) => {
82                if Self::can_be_dict(v) {
83                    Type::Dict
84                } else {
85                    Type::Map
86                }
87            }
88        }
89    }
90
91    /// Parse a struct from this value
92    ///
93    /// ```
94    /// use mbon::data::Value;
95    ///
96    /// let foo: u32 = Value::Int(345).parse().unwrap();
97    /// assert_eq!(foo, 345);
98    /// ```
99    #[inline]
100    pub fn parse<'t, T>(&'t self) -> Result<T>
101    where
102        T: Deserialize<'t>,
103    {
104        T::deserialize(ValueDe::new(&self))
105    }
106
107    /// Dump a struct into a value
108    ///
109    /// ```
110    /// use mbon::data::Value;
111    ///
112    /// let obj: u32 = 345;
113    /// let val = Value::dump(obj).unwrap();
114    ///
115    /// if let Value::Int(v) = val {
116    ///     assert_eq!(v, 345);
117    /// } else {
118    ///     panic!("val is not an Int");
119    /// }
120    /// ```
121    #[inline]
122    pub fn dump<T>(value: T) -> Result<Self>
123    where
124        T: Serialize,
125    {
126        value.serialize(&mut ValueSer)
127    }
128
129    /// Parse an object from this value
130    ///
131    /// This will attempt to parse an Object only if the Value is an Object
132    /// type.
133    ///
134    /// ```
135    /// use mbon::object::ObjectParse;
136    /// use mbon::parser::Parser;
137    /// use mbon::error::Error;
138    /// use mbon::data::Value;
139    ///
140    /// struct Foo {
141    ///     a: i32,
142    ///     b: String,
143    /// }
144    ///
145    /// impl ObjectParse for Foo {
146    ///     type Error = Error;
147    ///
148    ///     fn parse_object(object: &[u8]) -> Result<Self, Self::Error> {
149    ///         let mut parser = Parser::from(object);
150    ///         let a = parser.next()?;
151    ///         let b = parser.next()?;
152    ///         Ok(Self { a, b })
153    ///     }
154    /// }
155    ///
156    /// let val = Value::Object(b"i\x00\x00\x32\x40s\x00\x00\x00\x05Hello".to_vec());
157    /// let foo: Foo = val.parse_obj().unwrap();
158    ///
159    /// assert_eq!(foo.a, 0x3240);
160    /// assert_eq!(foo.b, "Hello");
161    /// ```
162    pub fn parse_obj<T>(&self) -> Result<T>
163    where
164        T: ObjectParse,
165        <T as ObjectParse>::Error: std::error::Error + 'static,
166    {
167        if let Value::Object(data) = self {
168            Error::from_res(T::parse_object(data))
169        } else {
170            Err(Error::Expected(Type::Object))
171        }
172    }
173
174    /// Dump an object into this value
175    ///
176    /// ```
177    /// use mbon::object::ObjectDump;
178    /// use mbon::dumper::Dumper;
179    /// use mbon::error::Error;
180    /// use mbon::data::Value;
181    ///
182    /// struct Foo {
183    ///     a: i32,
184    ///     b: String,
185    /// }
186    ///
187    /// impl ObjectDump for Foo {
188    ///     type Error = Error;
189    ///
190    ///     fn dump_object(&self) -> Result<Vec<u8>, Self::Error> {
191    ///         let mut dumper = Dumper::new();
192    ///         dumper.write(&self.a);
193    ///         dumper.write(&self.b);
194    ///         Ok(dumper.writer())
195    ///     }
196    /// }
197    ///
198    /// let foo = Foo { a: 0x3240, b: "Hello".to_owned() };
199    /// let val = Value::dump_obj(foo).unwrap();
200    ///
201    /// if let Value::Object(v) = val {
202    ///     assert_eq!(v, b"i\x00\x00\x32\x40s\x00\x00\x00\x05Hello");
203    /// } else {
204    ///     panic!("val is not an Object");
205    /// }
206    /// ```
207    #[inline]
208    pub fn dump_obj<T>(value: T) -> Result<Self>
209    where
210        T: ObjectDump,
211        <T as ObjectDump>::Error: std::error::Error + 'static,
212    {
213        let data = Error::from_res(value.dump_object())?;
214        Ok(Value::Object(data))
215    }
216
217    /// Get the total size in bytes that this value uses in binary form
218    ///
219    /// ```
220    /// use mbon::data::Value;
221    ///
222    /// let value = Value::Int(42);
223    ///
224    /// assert_eq!(value.size(), 5);
225    /// ```
226    #[inline]
227    pub fn size(&self) -> usize {
228        Mark::from(self).size()
229    }
230
231    /// Get the size in bytes that the data will use in binary form
232    ///
233    /// ```
234    /// use mbon::data::Value;
235    ///
236    /// let value = Value::Int(42);
237    ///
238    /// assert_eq!(value.data_size(), 4);
239    /// ```
240    #[inline]
241    pub fn data_size(&self) -> usize {
242        Mark::from(self).data_size()
243    }
244
245    /// Get the size in bytes that the mark will use in binary form
246    ///
247    /// ```
248    /// use mbon::data::Value;
249    ///
250    /// let value = Value::Int(42);
251    ///
252    /// assert_eq!(value.mark_size(), 1);
253    /// ```
254    #[inline]
255    pub fn mark_size(&self) -> usize {
256        Mark::from(self).mark_size()
257    }
258
259    /// Check if a list can be stored as an array
260    ///
261    /// If all elements in the list have the same mark, then the list can be an
262    /// array.
263    ///
264    /// ```
265    /// use mbon::data::Value;
266    ///
267    /// let array = vec![Value::Int(32), Value::Int(42)];
268    /// assert_eq!(Value::can_be_array(&array), true);
269    ///
270    /// let list = vec![Value::Int(32), Value::Char(42)];
271    /// assert_eq!(Value::can_be_array(&list), false);
272    /// ```
273    pub fn can_be_array<'t, I>(list: I) -> bool
274    where
275        I: IntoIterator<Item = &'t Value>,
276    {
277        let mut iter = list.into_iter();
278        if let Some(first) = iter.next() {
279            let first_mark = Mark::from_value(first);
280
281            for val in iter {
282                let mark = Mark::from_value(val);
283                if mark != first_mark {
284                    return false;
285                }
286            }
287            true
288        } else {
289            false
290        }
291    }
292
293    /// Check if a map can be stored as a dict
294    ///
295    /// If each key-value pair uses the same marks then the map can be a dict.
296    ///
297    /// ```
298    /// use mbon::data::Value;
299    ///
300    /// let dict = vec![
301    ///     (Value::Str("a".to_owned()), Value::Int(32)),
302    ///     (Value::Str("b".to_owned()), Value::Int(42)),
303    /// ];
304    /// assert_eq!(Value::can_be_dict(&dict), true);
305    ///
306    /// let map = vec![
307    ///     (Value::Str("a".to_owned()), Value::Int(32)),
308    ///     (Value::Str("hello".to_owned()), Value::Int(42)),
309    /// ];
310    /// assert_eq!(Value::can_be_dict(&map), false);
311    /// ```
312    pub fn can_be_dict<'t, I>(map: I) -> bool
313    where
314        I: IntoIterator<Item = &'t (Value, Value)>,
315    {
316        let mut iter = map.into_iter();
317        if let Some((first_k, first_v)) = iter.next() {
318            let key_mark: Mark = first_k.into();
319            let val_mark: Mark = first_v.into();
320
321            for (k, v) in iter {
322                let km: Mark = k.into();
323                let vm: Mark = v.into();
324                if km != key_mark || vm != val_mark {
325                    return false;
326                }
327            }
328            true
329        } else {
330            false
331        }
332    }
333}
334
335impl AsRef<Value> for Value {
336    fn as_ref(&self) -> &Value {
337        &self
338    }
339}
340
341/// An indicator of what's contained in the value.
342///
343/// This is the first thing that is read/written in mbon, and it will tell the
344/// reader how to read the value that the mark represents.
345#[derive(Debug, PartialEq, Eq)]
346pub enum Mark {
347    Long,
348    Int,
349    Short,
350    Char,
351    Float,
352    Double,
353    Bytes(usize),
354    Str(usize),
355    Object(usize),
356    Enum(Box<Mark>),
357    Null,
358    Array(usize, Box<Mark>),
359    List(usize),
360    Dict(usize, Box<Mark>, Box<Mark>),
361    Map(usize),
362}
363
364impl Mark {
365    /// Get the size in bytes that the mark will use in binary form
366    ///
367    /// ```
368    /// use mbon::data::Mark;
369    ///
370    /// assert_eq!(Mark::Int.mark_size(), 1);
371    /// ```
372    pub fn mark_size(&self) -> usize {
373        match self {
374            Mark::Long => 1,
375            Mark::Int => 1,
376            Mark::Short => 1,
377            Mark::Char => 1,
378            Mark::Float => 1,
379            Mark::Double => 1,
380            Mark::Bytes(_) => 5,
381            Mark::Str(_) => 5,
382            Mark::Object(_) => 5,
383            Mark::Enum(m) => 1 + m.mark_size(),
384            Mark::Null => 1,
385            Mark::Array(_, m) => 5 + m.mark_size(),
386            Mark::List(_) => 5,
387            Mark::Dict(_, k, v) => 5 + k.mark_size() + v.mark_size(),
388            Mark::Map(_) => 5,
389        }
390    }
391
392    /// Get the size in bytes that the data will use in binary form
393    ///
394    /// ```
395    /// use mbon::data::Mark;
396    ///
397    /// assert_eq!(Mark::Int.data_size(), 4);
398    /// ```
399    pub fn data_size(&self) -> usize {
400        match self {
401            Mark::Long => 8,
402            Mark::Int => 4,
403            Mark::Short => 2,
404            Mark::Char => 1,
405            Mark::Float => 4,
406            Mark::Double => 8,
407            Mark::Bytes(n) => *n,
408            Mark::Str(n) => *n,
409            Mark::Object(n) => *n,
410            Mark::Enum(m) => m.data_size() + 4,
411            Mark::Null => 0,
412            Mark::Array(len, m) => len * m.data_size(),
413            Mark::List(n) => *n,
414            Mark::Dict(len, k, v) => len * (k.data_size() + v.data_size()),
415            Mark::Map(n) => *n,
416        }
417    }
418
419    /// Get the total size in bytes that this value uses in binary form
420    ///
421    /// ```
422    /// use mbon::data::Mark;
423    ///
424    /// assert_eq!(Mark::Int.size(), 5);
425    /// ```
426    #[inline]
427    pub fn size(&self) -> usize {
428        self.mark_size() + self.data_size()
429    }
430
431    /// Get the type of this mark
432    pub fn get_type(&self) -> Type {
433        match self {
434            Mark::Long => Type::Long,
435            Mark::Int => Type::Int,
436            Mark::Short => Type::Short,
437            Mark::Char => Type::Char,
438            Mark::Float => Type::Float,
439            Mark::Double => Type::Double,
440            Mark::Bytes(_) => Type::Bytes,
441            Mark::Str(_) => Type::Str,
442            Mark::Object(_) => Type::Object,
443            Mark::Enum(_) => Type::Enum,
444            Mark::Null => Type::Null,
445            Mark::Array(_, _) => Type::Array,
446            Mark::List(_) => Type::List,
447            Mark::Dict(_, _, _) => Type::Dict,
448            Mark::Map(_) => Type::Map,
449        }
450    }
451
452    /// Get the mark from a value
453    ///
454    /// ```
455    /// use mbon::data::{Mark, Value};
456    ///
457    /// assert_eq!(Mark::from_value(Value::Int(32)), Mark::Int);
458    /// assert_eq!(
459    ///     Mark::from_value(Value::Str("Hello".to_owned())),
460    ///     Mark::Str(5)
461    /// );
462    /// ```
463    pub fn from_value(val: impl AsRef<Value>) -> Self {
464        match val.as_ref() {
465            Value::Long(_) => Self::Long,
466            Value::Int(_) => Self::Int,
467            Value::Short(_) => Self::Short,
468            Value::Char(_) => Self::Char,
469            Value::Float(_) => Self::Float,
470            Value::Double(_) => Self::Double,
471            Value::Bytes(v) => Self::Bytes(v.len()),
472            Value::Str(v) => Self::Str(v.len()),
473            Value::Object(v) => Self::Object(v.len()),
474            Value::Enum(_, v) => Self::Enum(Box::new(Self::from_value(v))),
475            Value::Null => Self::Null,
476            Value::List(v) => {
477                if Value::can_be_array(v) {
478                    let first = v.first().unwrap();
479                    Self::Array(v.len(), Box::new(Self::from_value(first)))
480                } else {
481                    Self::List(v.iter().map(|v| Self::from_value(v).size()).sum())
482                }
483            }
484            Value::Map(v) => {
485                if Value::can_be_dict(v) {
486                    let (first_k, first_v) = v.first().unwrap();
487                    Self::Dict(
488                        v.len(),
489                        Box::new(Self::from_value(first_k)),
490                        Box::new(Self::from_value(first_v)),
491                    )
492                } else {
493                    Self::Map(
494                        v.iter()
495                            .map(|(k, v)| Self::from_value(k).size() + Self::from_value(v).size())
496                            .sum(),
497                    )
498                }
499            }
500        }
501    }
502}
503
504impl AsRef<Mark> for Mark {
505    fn as_ref(&self) -> &Mark {
506        self
507    }
508}
509
510impl From<Mark> for Type {
511    fn from(m: Mark) -> Self {
512        m.get_type()
513    }
514}
515
516impl<'t> From<&'t Mark> for Type {
517    fn from(m: &'t Mark) -> Self {
518        m.get_type()
519    }
520}
521
522impl From<Value> for Mark {
523    fn from(v: Value) -> Self {
524        Self::from_value(v)
525    }
526}
527
528impl<'t> From<&'t Value> for Mark {
529    fn from(v: &'t Value) -> Self {
530        Self::from_value(v)
531    }
532}
533
534/// An indicator for what type of value is stored
535///
536/// This is the first byte that is read/written and indicates how to read the
537/// mark that is contained.
538#[derive(Debug, Clone, Copy, PartialEq, Eq)]
539pub enum Type {
540    Long,
541    Int,
542    Short,
543    Char,
544    Float,
545    Double,
546    Bytes,
547    Str,
548    Object,
549    Enum,
550    Null,
551    Array,
552    List,
553    Dict,
554    Map,
555}
556
557impl Display for Type {
558    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
559        match self {
560            Type::Long => f.write_str("Long"),
561            Type::Int => f.write_str("Int"),
562            Type::Short => f.write_str("Short"),
563            Type::Char => f.write_str("Char"),
564            Type::Float => f.write_str("Float"),
565            Type::Double => f.write_str("Double"),
566            Type::Bytes => f.write_str("Bytes"),
567            Type::Str => f.write_str("Str"),
568            Type::Object => f.write_str("Object"),
569            Type::Enum => f.write_str("Enum"),
570            Type::Null => f.write_str("Null"),
571            Type::Array => f.write_str("Array"),
572            Type::List => f.write_str("List"),
573            Type::Dict => f.write_str("Dict"),
574            Type::Map => f.write_str("Map"),
575        }
576    }
577}
578
579impl Type {
580    /// Get the prefix that will indicate the value type
581    #[inline]
582    pub fn prefix(&self) -> u8 {
583        match self {
584            Type::Long => b'l',
585            Type::Int => b'i',
586            Type::Short => b'h',
587            Type::Char => b'c',
588            Type::Float => b'f',
589            Type::Double => b'd',
590            Type::Bytes => b'b',
591            Type::Str => b's',
592            Type::Object => b'o',
593            Type::Enum => b'e',
594            Type::Null => b'n',
595            Type::Array => b'a',
596            Type::List => b'A',
597            Type::Dict => b'm',
598            Type::Map => b'M',
599        }
600    }
601
602    /// Get the type from the given prefix
603    pub fn from_prefix(prefix: u8) -> Result<Self> {
604        match prefix {
605            b'l' => Ok(Type::Long),
606            b'i' => Ok(Type::Int),
607            b'h' => Ok(Type::Short),
608            b'c' => Ok(Type::Char),
609            b'f' => Ok(Type::Float),
610            b'd' => Ok(Type::Double),
611            b'b' => Ok(Type::Bytes),
612            b's' => Ok(Type::Str),
613            b'o' => Ok(Type::Object),
614            b'e' => Ok(Type::Enum),
615            b'n' => Ok(Type::Null),
616            b'a' => Ok(Type::Array),
617            b'A' => Ok(Type::List),
618            b'm' => Ok(Type::Dict),
619            b'M' => Ok(Type::Map),
620            _ => Err(Error::DataError(format!("Unknown prefix `{}`", prefix))),
621        }
622    }
623}