dsf_core/wire/
container.rs

1use crate::types::*;
2
3use crate::base::header::{offsets, HEADER_LEN};
4use crate::options::{Options, OptionsIter};
5
6use super::header::WireHeader;
7
8/// Container object provides base field accessors over an arbitrary (mutable or immutable) buffers
9/// See https://lab.whitequark.org/notes/2016-12-13/abstracting-over-mutability-in-rust/ for details
10#[derive(Clone, Debug, PartialEq)]
11pub struct Container<T: ImmutableData> {
12    /// Internal data buffer
13    pub(crate) buff: T,
14    /// Length of object in container buffer
15    pub(crate) len: usize,
16}
17
18impl<'a, T: ImmutableData> Container<T> {
19    /// Create a new container object from an existing buffer
20    /// This parses the header and splits the data into fields to simplify access
21    pub fn from(buff: T) -> (Self, usize) {
22        let len = buff.as_ref().len();
23        let c = Container { buff, len };
24        let n = c.len();
25        (c, n)
26    }
27
28    /// Fetch wire header
29    pub fn header(&self) -> WireHeader<&[u8]> {
30        WireHeader {
31            buff: &self.buff.as_ref()[..HEADER_LEN],
32        }
33    }
34
35    /// Fetch object ID
36    pub fn id(&self) -> &[u8] {
37        let data = self.buff.as_ref();
38
39        &data[offsets::ID..offsets::BODY]
40    }
41
42    /// Return the body of data
43    pub fn body(&self) -> &[u8] {
44        let data = self.buff.as_ref();
45
46        let n = HEADER_LEN + ID_LEN;
47        let s = self.header().data_len();
48        &data[n..n + s]
49    }
50
51    /// Return the private options section data
52    pub fn private_options(&self) -> &[u8] {
53        let data = self.buff.as_ref();
54
55        let n = HEADER_LEN + ID_LEN + self.header().data_len();
56        let s = self.header().private_options_len();
57        &data[n..n + s]
58    }
59
60    /// Return the public options section data
61    pub fn public_options(&self) -> impl Iterator<Item = Options> + '_ {
62        let data = self.buff.as_ref();
63        let header = self.header();
64
65        let n = HEADER_LEN + ID_LEN + header.data_len() + header.private_options_len();
66        let s = header.public_options_len();
67        OptionsIter::new(&data[n..n + s])
68    }
69
70    /// Return the signed portion of the message for signing or verification
71    pub fn signed(&self) -> &[u8] {
72        let data = self.buff.as_ref();
73        let n = self.len();
74
75        &data[..n - SIGNATURE_LEN]
76    }
77
78    /// Return the signature portion of the message for verification
79    pub fn signature(&self) -> &[u8] {
80        let data = self.buff.as_ref();
81
82        let n = self.len() - SIGNATURE_LEN;
83        let s = SIGNATURE_LEN;
84
85        &data[n..n + s]
86    }
87
88    /// Return the total length of the object (from the header)
89    pub fn len(&self) -> usize {
90        let header = self.header();
91
92        HEADER_LEN
93            + ID_LEN
94            + header.data_len()
95            + header.private_options_len()
96            + header.public_options_len()
97            + SIGNATURE_LEN
98    }
99
100    /// Verify the contents of a given container
101    /// This calls the provided verifier with the id, body, and signature and forwards the result to the caller
102    pub fn verify<V, E>(&self, mut verifier: V) -> Result<bool, E>
103    where
104        V: FnMut(&Id, &Signature, &[u8]) -> Result<bool, E>,
105    {
106        let id: Id = self.id().into();
107        let data = self.signed();
108        let sig: Signature = self.signature().into();
109
110        (verifier)(&id, &sig, &data)
111    }
112
113    /// Fetch the raw data using internal header length
114    pub fn raw(&self) -> &[u8] {
115        let data = self.buff.as_ref();
116        let len = self.len();
117
118        &data[0..len]
119    }
120}