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
use std::io::Cursor;

use binrw::{helpers::count, BinRead, BinReaderExt, BinWrite};
use rmpv::Value;

pub struct FlowRecord(Value);

impl BinWrite for FlowRecord {
    type Args<'a> = ();

    fn write_options<W: std::io::Write + std::io::Seek>(
        &self,
        writer: &mut W,
        _endian: binrw::Endian,
        _args: Self::Args<'_>,
    ) -> binrw::BinResult<()> {
        let mut data = Vec::new();

        if let Err(why) = rmpv::encode::write_value(&mut data, &self.0) {
            return Err(binrw::Error::Custom {
                pos: writer.stream_position()?,
                err: Box::new(why),
            });
        }

        let length: u32 = data.len().try_into().unwrap();
        length.write_be(writer)?;
        data.write_be(writer)?;
        Ok(())
    }
}

impl BinRead for FlowRecord {
    type Args<'a> = ();

    fn read_options<R: std::io::Read + std::io::Seek>(
        reader: &mut R,
        endian: binrw::Endian,
        args: Self::Args<'_>,
    ) -> binrw::BinResult<Self> {
        let length: u32 = reader.read_be()?;
        let data: Vec<u8> = count(length.try_into().unwrap())(reader, endian, args)?;

        match rmpv::decode::read_value(&mut Cursor::new(data)) {
            Ok(value) => Ok(Self(value)),
            Err(why) => Err(binrw::Error::Custom {
                pos: reader.stream_position()?,
                err: Box::new(why),
            }),
        }
    }
}

impl From<Value> for FlowRecord {
    fn from(data: Value) -> Self {
        Self(data)
    }
}

impl From<FlowRecord> for Value {
    fn from(value: FlowRecord) -> Self {
        value.0
    }
}