abin/binary/
bin_segment.rs

1use crate::{AnyBin, Segment};
2
3/// A segment; segments can be joined to create binaries. See `BinBuilder`,
4/// `SegmentIterator` and `SegmentsSlice`.
5///
6/// ```rust
7/// use abin::{NewBin, BinSegment, Bin, AnyBin, BinBuilder};
8///
9/// let mut builder = NewBin::builder();
10/// builder.push(BinSegment::Static("Hello, ".as_bytes()));
11/// builder.push(BinSegment::Static("World!".as_bytes()));
12/// let bin : Bin = builder.build();
13///
14/// assert_eq!("Hello, World!".as_bytes(), bin.as_slice());
15/// ```
16#[derive(Debug, Clone)]
17pub enum BinSegment<'a, TAnyBin: AnyBin> {
18    Slice(&'a [u8]),
19    Static(&'static [u8]),
20    Bin(TAnyBin),
21    GivenVec(Vec<u8>),
22    Bytes128(Bytes128),
23    Empty,
24}
25
26impl<'a, TAnyBin> Segment for BinSegment<'a, TAnyBin>
27where
28    TAnyBin: AnyBin,
29{
30    #[inline]
31    fn number_of_bytes(&self) -> usize {
32        self.as_slice().len()
33    }
34
35    #[inline]
36    fn empty() -> Self {
37        Self::Empty
38    }
39}
40
41impl<'a, TAnyBin> BinSegment<'a, TAnyBin>
42where
43    TAnyBin: AnyBin,
44{
45    pub fn as_slice(&self) -> &[u8] {
46        match self {
47            BinSegment::Slice(slice) => *slice,
48            BinSegment::Static(slice) => *slice,
49            BinSegment::Bin(bin) => bin.as_slice(),
50            BinSegment::GivenVec(vec) => vec.as_slice(),
51            BinSegment::Bytes128(bytes) => bytes.as_slice(),
52            BinSegment::Empty => &[],
53        }
54    }
55
56    pub fn from_slice(slice: &'a [u8]) -> Self {
57        Self::Slice(slice)
58    }
59}
60
61impl<'a, TAnyBin> From<&'static [u8]> for BinSegment<'a, TAnyBin>
62where
63    TAnyBin: AnyBin,
64{
65    fn from(slice: &'static [u8]) -> Self {
66        Self::Static(slice)
67    }
68}
69
70impl<'a, TAnyBin> From<TAnyBin> for BinSegment<'a, TAnyBin>
71where
72    TAnyBin: AnyBin,
73{
74    fn from(bin: TAnyBin) -> Self {
75        Self::Bin(bin)
76    }
77}
78
79impl<'a, TAnyBin> From<Vec<u8>> for BinSegment<'a, TAnyBin>
80where
81    TAnyBin: AnyBin,
82{
83    fn from(vec: Vec<u8>) -> Self {
84        Self::GivenVec(vec)
85    }
86}
87
88impl<'a, TAnyBin> From<Bytes128> for BinSegment<'a, TAnyBin>
89where
90    TAnyBin: AnyBin,
91{
92    fn from(bytes: Bytes128) -> Self {
93        Self::Bytes128(bytes)
94    }
95}
96
97const BYTES_128_LEN: usize = 16;
98
99/// Up to 16 bytes / 128 bit stored on the stack.
100///
101/// This can be used when constructing segments from primitive types (such as char, u64, f32
102/// or f64).
103#[derive(Debug, Copy, Clone, Eq, PartialEq)]
104pub struct Bytes128 {
105    bytes: [u8; BYTES_128_LEN],
106    len: u8,
107}
108
109impl Bytes128 {
110    /// creates new bytes from given slice. Returns `None` if given slice contains more than
111    /// `max_number_of_bytes` bytes.
112    #[inline]
113    pub fn try_new(slice: &[u8]) -> Option<Self> {
114        let len = slice.len();
115        if len > BYTES_128_LEN {
116            None
117        } else {
118            let mut this = Self {
119                bytes: [0u8; BYTES_128_LEN],
120                len: len as u8,
121            };
122            let bytes = &mut this.bytes[0..len];
123            bytes.copy_from_slice(slice);
124            Some(this)
125        }
126    }
127
128    /// The maximum number of bytes that can be stored.
129    pub const fn max_number_of_bytes() -> usize {
130        BYTES_128_LEN
131    }
132
133    #[inline]
134    pub fn as_slice(&self) -> &[u8] {
135        &self.bytes[0..self.len as usize]
136    }
137}
138
139impl From<u8> for Bytes128 {
140    fn from(byte: u8) -> Self {
141        Self {
142            bytes: [byte, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
143            len: 1,
144        }
145    }
146}
147
148impl From<char> for Bytes128 {
149    fn from(chr: char) -> Self {
150        let mut buf = [0u8; 4];
151        let string = chr.encode_utf8(&mut buf);
152        Self::try_new(string.as_bytes()).expect(
153            "Implementation error: Converting from \
154        char cannot fail (since char takes 4 bytes whereas Bytes128 can take up to 16 bytes).",
155        )
156    }
157}