Skip to main content

sark_http/field/metadata/block/buffer/
mod.rs

1use o3::{alloc, buffer::write::Sink};
2
3use crate::field::metadata::{
4    block::{Name, Named, Scan, Validation, Value, Valued},
5    map::record::Span,
6};
7
8mod sealed;
9pub(super) use sealed::Sealed;
10
11pub type Names = Buffer<Scan>;
12pub type Values = Buffer<Value>;
13
14/// The two native metadata scanners accepted by retained buffers.
15pub trait Scanner: Sealed + Copy {
16    type Proof: Copy;
17    const EMPTY: Self;
18    fn push(&mut self, byte: u8);
19}
20
21impl Scanner for Scan {
22    type Proof = Name;
23    const EMPTY: Self = Self::new();
24    fn push(&mut self, byte: u8) {
25        self.push(byte);
26    }
27}
28
29impl Scanner for Value {
30    type Proof = Validation;
31    const EMPTY: Self = Self::new();
32    fn push(&mut self, byte: u8) {
33        self.push(byte);
34    }
35}
36
37/// Immutable bytes paired with their unfinished metadata scan.
38#[derive(Clone, Copy)]
39pub struct Prefix<'a, S: Scanner> {
40    span: Span<'a>,
41    scan: S,
42}
43
44impl<'a, S: Scanner> Prefix<'a, S> {
45    pub(crate) const fn from_scanned(span: Span<'a>, scan: S) -> Self {
46        Self { span, scan }
47    }
48}
49
50/// Reusable metadata storage that retains classification with its bytes.
51pub struct Buffer<S: Scanner> {
52    bytes: Vec<u8>,
53    scan: S,
54    complete: Option<S::Proof>,
55}
56
57impl<S: Scanner> Buffer<S> {
58    pub const fn new() -> Self {
59        Self {
60            bytes: Vec::new(),
61            scan: S::EMPTY,
62            complete: None,
63        }
64    }
65
66    pub fn clear(&mut self) {
67        self.bytes.clear();
68        self.scan = S::EMPTY;
69        self.complete = None;
70    }
71
72    pub fn len(&self) -> usize {
73        self.bytes.len()
74    }
75
76    pub fn is_empty(&self) -> bool {
77        self.bytes.is_empty()
78    }
79
80    pub fn as_slice(&self) -> &[u8] {
81        &self.bytes
82    }
83
84    pub fn copy_prefix(&mut self, prefix: Prefix<'_, S>) -> Result<(), alloc::Error> {
85        self.replace(prefix.span)?;
86        self.scan = prefix.scan;
87        Ok(())
88    }
89
90    fn replace(&mut self, span: Span<'_>) -> Result<(), alloc::Error> {
91        self.clear();
92        let (first, second) = span.parts();
93        self.bytes.write_slices([first, second])
94    }
95
96    pub fn writer(&mut self, limit: Option<usize>) -> Writer<'_, S> {
97        let mark = (self.bytes.len(), self.scan, self.complete);
98        Writer {
99            buffer: self,
100            mark,
101            limit,
102            retained: true,
103        }
104    }
105}
106
107impl<S: Scanner> Default for Buffer<S> {
108    fn default() -> Self {
109        Self::new()
110    }
111}
112
113impl Buffer<Scan> {
114    pub fn named(&self) -> Named<'_> {
115        Named::from_scanned(
116            Span::from_slice(&self.bytes),
117            self.complete.unwrap_or_else(|| self.scan.finish()),
118        )
119    }
120
121    pub fn copy_from(&mut self, name: Named<'_>) -> Result<(), alloc::Error> {
122        self.replace(name.span())?;
123        self.complete = Some(name.proof());
124        Ok(())
125    }
126}
127
128impl Buffer<Value> {
129    pub fn valued(&self) -> Valued<'_> {
130        Valued::from_scanned(
131            Span::from_slice(&self.bytes),
132            self.complete.unwrap_or_else(|| self.scan.finish()),
133        )
134    }
135
136    pub fn copy_from(&mut self, value: Valued<'_>) -> Result<(), alloc::Error> {
137        self.replace(value.span())?;
138        self.complete = Some(value.validation());
139        Ok(())
140    }
141}
142
143/// One append transaction, including its owner-bound rollback checkpoint.
144pub struct Writer<'a, S: Scanner> {
145    buffer: &'a mut Buffer<S>,
146    mark: (usize, S, Option<S::Proof>),
147    limit: Option<usize>,
148    retained: bool,
149}
150
151impl<S: Scanner> Writer<'_, S> {
152    pub fn len(&self) -> usize {
153        self.buffer.len()
154    }
155
156    pub fn is_empty(&self) -> bool {
157        self.buffer.is_empty()
158    }
159
160    pub const fn is_retained(&self) -> bool {
161        self.retained
162    }
163
164    pub fn rollback(self) {
165        self.buffer.bytes.truncate(self.mark.0);
166        self.buffer.scan = self.mark.1;
167        self.buffer.complete = self.mark.2;
168    }
169
170    fn reserve(&mut self, extra: Option<usize>) -> Result<bool, alloc::Error> {
171        if !self.retained {
172            return Ok(false);
173        }
174        let Some(extra) = extra else {
175            self.retained = false;
176            return Ok(false);
177        };
178        let end = self.buffer.len().checked_add(extra);
179        if end.is_none_or(|end| self.limit.is_some_and(|limit| end > limit)) {
180            self.retained = false;
181            return Ok(false);
182        }
183        alloc::VecExt::try_reserve(&mut self.buffer.bytes, extra)?;
184        if extra != 0 && self.buffer.complete.take().is_some() {
185            self.buffer.scan = S::EMPTY;
186            for &byte in &self.buffer.bytes {
187                self.buffer.scan.push(byte);
188            }
189        }
190        Ok(true)
191    }
192
193    fn extend(&mut self, bytes: &[u8]) {
194        self.buffer.bytes.extend_from_slice(bytes);
195        for &byte in bytes {
196            self.buffer.scan.push(byte);
197        }
198    }
199}
200
201impl<S: Scanner> Sink for Writer<'_, S> {
202    type Error = alloc::Error;
203
204    fn write_slice(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
205        if self.reserve(Some(bytes.len()))? {
206            self.extend(bytes);
207        }
208        Ok(())
209    }
210
211    fn write_slices<const N: usize>(&mut self, slices: [&[u8]; N]) -> Result<(), Self::Error> {
212        let extra = slices
213            .iter()
214            .try_fold(0usize, |len, bytes| len.checked_add(bytes.len()));
215        if self.reserve(extra)? {
216            for bytes in slices {
217                self.extend(bytes);
218            }
219        }
220        Ok(())
221    }
222}