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}