Skip to main content

abin/common/
segments_slice.rs

1use core::mem;
2
3use crate::common::segment_iterator::SegmentIterator;
4use crate::Segment;
5
6/// It's an implementation of `SegmentIterator` that does not heap-allocate. Alternatives are
7/// `BinBuilder` and `StrBuilder`; `SegmentsSlice` is less flexible but cheaper
8/// (smaller stack; faster).
9///
10/// ```rust
11/// use abin::{BinSegment, SegmentsSlice, Bin, NewBin, BinFactory, AnyBin};
12///
13/// let segments = &mut [BinSegment::Static("Hello, ".as_bytes()),
14///     BinSegment::Static("World!".as_bytes())];
15/// let iterator = SegmentsSlice::new(segments);
16/// let bin : Bin = NewBin::from_segments(iterator);
17/// assert_eq!("Hello, World!".as_bytes(), bin.as_slice());
18/// ```
19pub struct SegmentsSlice<'a, TSegment> {
20    slice: &'a mut [TSegment],
21    number_of_bytes: usize,
22    pos: usize,
23    /// this is set to the index of the single item (if there's just one single item).
24    single_index: Option<usize>,
25}
26
27impl<'a, TSegment> SegmentsSlice<'a, TSegment>
28where
29    TSegment: Segment,
30{
31    /// Important: The given slice might be modified; do not use this slice.
32    #[inline]
33    pub fn new(slice: &'a mut [TSegment]) -> Self {
34        // analyze content.
35        let mut number_of_bytes = 0;
36        let mut no_item_yet = true;
37        let mut single_index = None;
38        for (index, item) in slice.iter().enumerate() {
39            let item_len = item.number_of_bytes();
40            // ignore all empty items
41            if item_len > 0 {
42                number_of_bytes += item_len;
43                if no_item_yet {
44                    single_index = Some(index);
45                    no_item_yet = false;
46                } else {
47                    // more than one
48                    single_index = None;
49                }
50            }
51        }
52
53        Self {
54            slice,
55            number_of_bytes,
56            pos: 0,
57            single_index,
58        }
59    }
60
61    #[inline]
62    fn remaining(&self) -> usize {
63        let len = self.slice.len();
64        if self.pos < len {
65            len - self.pos
66        } else {
67            0
68        }
69    }
70
71    fn take(&mut self, index: usize) -> Option<TSegment> {
72        if index < self.slice.len() {
73            let empty = TSegment::empty();
74            Some(mem::replace(&mut self.slice[index], empty))
75        } else {
76            None
77        }
78    }
79}
80
81impl<'a, TSegment> SegmentIterator<TSegment> for SegmentsSlice<'a, TSegment>
82where
83    TSegment: Segment,
84{
85    fn exact_number_of_bytes(&self) -> Option<usize> {
86        Some(self.number_of_bytes)
87    }
88
89    fn is_empty(&self) -> bool {
90        self.number_of_bytes == 0
91    }
92
93    fn single(mut self) -> Result<TSegment, Self>
94    where
95        Self: Sized,
96    {
97        if let Some(single_index) = self.single_index {
98            let taken = SegmentsSlice::take(&mut self, single_index);
99            Ok(taken.expect("Implementation error (single_index is invalid)"))
100        } else {
101            Err(self)
102        }
103    }
104}
105
106impl<'a, TSegment: Segment> Iterator for SegmentsSlice<'a, TSegment> {
107    type Item = TSegment;
108
109    fn next(&mut self) -> Option<Self::Item> {
110        let item = SegmentsSlice::take(self, self.pos);
111        self.pos += 1;
112        item
113    }
114}
115
116impl<'a, TSegment: Segment> ExactSizeIterator for SegmentsSlice<'a, TSegment> {
117    #[inline]
118    fn len(&self) -> usize {
119        self.remaining()
120    }
121}