Skip to main content

ferroui_base/rendering/composition/drawing/
render_data_writer.rs

1use super::{IRenderDataPayload, RenderDataOpcode};
2use crate::rendering::composition::transport::BatchValue;
3
4/// Appends the operations of a render data stream to a byte buffer.
5///
6/// Upstream blits unmanaged structs into a pooled array; the port encodes
7/// values with [`BatchValue`] (fields in declaration order, little-endian),
8/// the encoding of the batch transport, so that no `unsafe` is needed.
9#[derive(Debug, Default)]
10pub struct RenderDataWriter {
11    buffer: Option<Vec<u8>>,
12    length: usize,
13}
14
15impl RenderDataWriter {
16    pub fn new() -> Self {
17        Self::default()
18    }
19
20    /// The number of bytes written.
21    pub fn length(&self) -> usize {
22        self.length
23    }
24
25    /// The bytes written.
26    pub fn written(&self) -> &[u8] {
27        match &self.buffer {
28            Some(buffer) => &buffer[..self.length],
29            None => &[],
30        }
31    }
32
33    /// The buffer, cut to `length`: bytes past a rewind are overwritten.
34    /// It starts at 256 bytes and doubles when it grows.
35    fn buffer(buffer: &mut Option<Vec<u8>>, length: usize) -> &mut Vec<u8> {
36        let buffer = buffer.get_or_insert_with(|| Vec::with_capacity(256));
37        buffer.truncate(length);
38        buffer
39    }
40
41    /// Makes room for `size` more bytes and returns them.
42    fn advance(&mut self, size: usize) -> &mut [u8] {
43        let start = self.length;
44        self.length = start + size;
45        let buffer = Self::buffer(&mut self.buffer, start);
46        buffer.resize(start + size, 0);
47        &mut buffer[start..]
48    }
49
50    /// Appends `count` bytes for the caller to fill.
51    pub fn reserve(&mut self, count: usize) -> &mut [u8] {
52        self.advance(count)
53    }
54
55    /// Drops everything written after `length` bytes.
56    pub fn rewind(&mut self, length: usize) {
57        self.length = length;
58    }
59
60    /// Appends a value.
61    pub fn write<T: BatchValue>(&mut self, value: T) {
62        let buffer = Self::buffer(&mut self.buffer, self.length);
63        value.write_to(buffer);
64        self.length = buffer.len();
65    }
66
67    /// Appends an opcode.
68    pub fn write_opcode(&mut self, opcode: RenderDataOpcode) {
69        self.write(opcode);
70    }
71
72    /// Appends the opcode of a payload, then the payload.
73    pub fn write_payload<T: IRenderDataPayload>(&mut self, payload: T) {
74        self.write(T::OPCODE);
75        self.write(payload);
76    }
77
78    /// Releases the buffer.
79    pub fn dispose(&mut self) {
80        self.buffer = None;
81        self.length = 0;
82    }
83}