1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use std::io::{Read, Write};
use crate::{DecodeError, EncodeError, Value, PackableStructSum};
use crate::packable::{Pack, Unpack};

#[derive(Debug, Clone, PartialEq)]
/// An anonymous, generic variant for structure values. It does denote different structures by
/// a `tag_byte` field; all fields are written and read as [`Value`](crate::value::Value) in the
/// order in which they were given. This allows for parsing of any structure which is validly
/// encoded, valid in the PackStream specification sense, i.e. the struct marker and the field
/// size, a tag byte denoting the struct type and then a list of the fields.
///
/// It does not allow for recursive patterns; in a struct there is no other structure allowed.
///
/// ## Encode and Decode
/// Encoding and Decoding is given by the generic [`Pack`](crate::packable::Pack) and [`Unpack`](crate::packable::Unpack)
/// implementation for `Value<S>` where `S: `[`PackableStructSum`](crate::structure::struct_sum::PackableStructSum):
/// ```
/// # use packs::structure::generic_struct::GenericStruct;
/// # use packs::value::Value;
/// # use packs::packable::{Pack, Unpack};
/// let s = GenericStruct {
///         tag_byte: 0x01,
///         fields: vec!(Value::Float(42.0), Value::String(String::from("hello world"))),
/// };
///
/// let value = Value::Structure(s);
///
/// let mut buffer = Vec::new();
/// value.encode(&mut buffer).unwrap();
///
/// let res = <Value<GenericStruct>>::decode(&mut buffer.as_slice()).unwrap();
///
/// assert_eq!(res, value);
/// ```
pub struct GenericStruct {
    pub tag_byte: u8,
    pub fields: Vec<Value<()>>,
}

impl PackableStructSum for GenericStruct {
    fn read_struct_body<T: Read>(size: usize, tag_byte: u8, reader: &mut T) -> Result<Self, DecodeError> {
        let mut fields = Vec::with_capacity(size);
        for _ in 0..size {
            let value = <Value<()>>::decode(reader)?;
            fields.push(value);
        }

        Ok(GenericStruct {
            tag_byte,
            fields,
        })
    }

    fn write_struct_body<T: Write>(&self, writer: &mut T) -> Result<usize, EncodeError> {
        let mut written = 0;
        for val in &self.fields {
            written += val.encode(writer)?;
        }
        Ok(written)
    }

    fn fields_len(&self) -> usize {
        self.fields.len()
    }

    fn tag_byte(&self) -> u8 {
        self.tag_byte
    }
}