dsf_core/wire/
header.rs

1use byteorder::{ByteOrder, NetworkEndian};
2
3use crate::base::header::{offsets, Header};
4use crate::types::{Flags, ImmutableData, Kind, MutableData};
5
6/// Header generic over arbitrary storage for wire encoding
7// TODO: decide what to do with the high / low level impls
8pub struct WireHeader<T: ImmutableData> {
9    pub(crate) buff: T,
10}
11
12impl<T: ImmutableData> From<&WireHeader<T>> for Header {
13    /// Build a base::Header object from a WireHeader
14    fn from(wh: &WireHeader<T>) -> Header {
15        Header::new(wh.application_id(), wh.kind(), wh.index(), wh.flags())
16    }
17}
18
19impl<T: ImmutableData> WireHeader<T> {
20    /// Create a new header object
21    pub fn new(buff: T) -> Self {
22        Self { buff }
23    }
24
25    pub fn protocol_version(&self) -> u16 {
26        NetworkEndian::read_u16(&self.buff.as_ref()[offsets::PROTO_VERSION..])
27    }
28
29    pub fn application_id(&self) -> u16 {
30        NetworkEndian::read_u16(&self.buff.as_ref()[offsets::APPLICATION_ID..])
31    }
32
33    pub fn kind(&self) -> Kind {
34        let raw = NetworkEndian::read_u16(&self.buff.as_ref()[offsets::OBJECT_KIND..]);
35        Kind::from(raw)
36    }
37
38    pub fn flags(&self) -> Flags {
39        let raw = NetworkEndian::read_u16(&self.buff.as_ref()[offsets::FLAGS..]);
40        unsafe { Flags::from_bits_unchecked(raw) }
41    }
42
43    pub fn index(&self) -> u16 {
44        NetworkEndian::read_u16(&self.buff.as_ref()[offsets::INDEX..])
45    }
46
47    pub fn data_len(&self) -> usize {
48        NetworkEndian::read_u16(&self.buff.as_ref()[offsets::DATA_LEN..]) as usize
49    }
50
51    pub fn private_options_len(&self) -> usize {
52        NetworkEndian::read_u16(&self.buff.as_ref()[offsets::PRIVATE_OPTIONS_LEN..]) as usize
53    }
54
55    pub fn public_options_len(&self) -> usize {
56        NetworkEndian::read_u16(&self.buff.as_ref()[offsets::PUBLIC_OPTIONS_LEN..]) as usize
57    }
58}
59
60impl<T: MutableData> WireHeader<T> {
61    /// Write a base::Header
62    pub fn encode(&mut self, h: &Header) {
63        self.set_protocol_version(h.protocol_version());
64        self.set_application_id(h.application_id());
65        self.set_kind(h.kind());
66        self.set_flags(h.flags());
67        self.set_index(h.index());
68    }
69
70    /// Set the protocol version
71    pub fn set_protocol_version(&mut self, version: u16) {
72        NetworkEndian::write_u16(&mut self.buff.as_mut()[offsets::PROTO_VERSION..], version)
73    }
74
75    /// Set the application ID
76    pub fn set_application_id(&mut self, application_id: u16) {
77        NetworkEndian::write_u16(
78            &mut self.buff.as_mut()[offsets::APPLICATION_ID..],
79            application_id,
80        )
81    }
82
83    /// Set object flags
84    pub fn set_flags(&mut self, flags: Flags) {
85        NetworkEndian::write_u16(&mut self.buff.as_mut()[offsets::FLAGS..], flags.bits())
86    }
87
88    /// Set the object kind
89    pub fn set_kind(&mut self, kind: Kind) {
90        NetworkEndian::write_u16(&mut self.buff.as_mut()[offsets::OBJECT_KIND..], kind.into())
91    }
92
93    /// Set object index
94    pub fn set_index(&mut self, index: u16) {
95        NetworkEndian::write_u16(&mut self.buff.as_mut()[offsets::INDEX..], index)
96    }
97
98    /// Set the body field length
99    pub fn set_data_len(&mut self, data_len: usize) {
100        NetworkEndian::write_u16(
101            &mut self.buff.as_mut()[offsets::DATA_LEN..],
102            data_len as u16,
103        )
104    }
105
106    /// Set the private options field length
107    pub fn set_private_options_len(&mut self, private_options_len: usize) {
108        NetworkEndian::write_u16(
109            &mut self.buff.as_mut()[offsets::PRIVATE_OPTIONS_LEN..],
110            private_options_len as u16,
111        )
112    }
113
114    /// Set the public options field length
115    pub fn set_public_options_len(&mut self, public_options_len: usize) {
116        NetworkEndian::write_u16(
117            &mut self.buff.as_mut()[offsets::PUBLIC_OPTIONS_LEN..],
118            public_options_len as u16,
119        )
120    }
121}
122
123#[cfg(test)]
124mod tests {
125
126    use super::*;
127
128    use crate::base::header::{Header, HEADER_LEN};
129
130    use crate::types::PageKind;
131
132    #[test]
133    fn test_encode_wire_header() {
134        // Create high level header
135        let h = Header::new(0, PageKind::Generic.into(), 1, Flags::SECONDARY);
136
137        // Create new wire header
138        let mut h1 = WireHeader::new([0u8; HEADER_LEN]);
139
140        // Encode high-level onto wire
141        h1.encode(&h);
142
143        // Parse high-level from wire
144        let h2 = Header::from(&h1);
145
146        // Check original / decoded match
147        assert_eq!(h, h2);
148    }
149}