Skip to main content

draco_core/
encoder_buffer.rs

1use crate::version::DEFAULT_MESH_VERSION;
2
3/// Output buffer for writing Draco bitstream data.
4///
5/// `EncoderBuffer` accumulates encoded bytes and supports both byte-aligned
6/// writes and packed bit-level encoding for entropy-coded sections. Encoders
7/// write into it; after encoding, [`data`](EncoderBuffer::data) returns the
8/// finished bitstream as a byte slice ready to hand to a `DecoderBuffer` or
9/// write to a file.
10pub struct EncoderBuffer {
11    buffer: Vec<u8>,
12    bit_encoder_active: bool,
13    bit_start_pos: usize,
14    current_bit_offset: usize,
15    version_major: u8,
16    version_minor: u8,
17    encode_bit_sequence_size: bool,
18}
19
20impl Default for EncoderBuffer {
21    fn default() -> Self {
22        Self {
23            buffer: Vec::new(),
24            bit_encoder_active: false,
25            bit_start_pos: 0,
26            current_bit_offset: 0,
27            // Default to the latest mesh version so standalone encode/decode
28            // (e.g. encode_symbols/decode_symbols) agrees with DecoderBuffer::new().
29            version_major: DEFAULT_MESH_VERSION.0,
30            version_minor: DEFAULT_MESH_VERSION.1,
31            encode_bit_sequence_size: false,
32        }
33    }
34}
35
36impl EncoderBuffer {
37    /// Creates an empty encoder buffer.
38    pub fn new() -> Self {
39        Self::default()
40    }
41
42    /// Sets the target Draco bitstream version.
43    pub fn set_version(&mut self, major: u8, minor: u8) {
44        self.version_major = major;
45        self.version_minor = minor;
46    }
47
48    /// Returns the target major bitstream version.
49    pub fn version_major(&self) -> u8 {
50        self.version_major
51    }
52
53    /// Returns the target minor bitstream version.
54    pub fn version_minor(&self) -> u8 {
55        self.version_minor
56    }
57
58    /// Returns the packed `0xMMmm` target bitstream version for ordered comparisons.
59    pub fn bitstream_version(&self) -> u16 {
60        crate::version::bitstream_version(self.version_major, self.version_minor)
61    }
62
63    /// Clears all encoded bytes and resets active bit encoding state.
64    pub fn clear(&mut self) {
65        self.buffer.clear();
66        self.bit_encoder_active = false;
67        self.current_bit_offset = 0;
68    }
69
70    /// Resizes the underlying byte buffer.
71    pub fn resize(&mut self, nbytes: usize) {
72        self.buffer.resize(nbytes, 0);
73    }
74
75    /// Starts writing a packed bit sequence.
76    pub fn start_bit_encoding(&mut self, required_bits: usize, encode_size: bool) -> bool {
77        if self.bit_encoder_active {
78            return false;
79        }
80        self.encode_bit_sequence_size = encode_size;
81        if encode_size {
82            // Reserve 8 bytes for the size (will be replaced by varint or fixed 8 bytes later)
83            for _ in 0..8 {
84                self.buffer.push(0);
85            }
86        }
87        let required_bytes = required_bits.div_ceil(8);
88        self.bit_start_pos = self.buffer.len();
89        self.buffer.resize(self.bit_start_pos + required_bytes, 0);
90        self.bit_encoder_active = true;
91        self.current_bit_offset = 0;
92        true
93    }
94
95    /// Finishes the active packed bit sequence.
96    pub fn end_bit_encoding(&mut self) {
97        if !self.bit_encoder_active {
98            return;
99        }
100        self.bit_encoder_active = false;
101
102        if self.encode_bit_sequence_size {
103            let encoded_bits = self.current_bit_offset;
104            let encoded_bytes = encoded_bits.div_ceil(8);
105            let bitstream_version = self.bitstream_version();
106
107            let mut var_size_buffer = Vec::new();
108            if bitstream_version >= 0x0202 {
109                // Encode size as varint
110                let mut v = encoded_bytes as u64;
111                loop {
112                    let mut byte = (v & 0x7F) as u8;
113                    v >>= 7;
114                    if v != 0 {
115                        byte |= 0x80;
116                        var_size_buffer.push(byte);
117                    } else {
118                        var_size_buffer.push(byte);
119                        break;
120                    }
121                }
122            } else {
123                // Encode size as fixed 8 bytes
124                var_size_buffer.extend_from_slice(&(encoded_bytes as u64).to_le_bytes());
125            }
126
127            let size_len = var_size_buffer.len();
128            let reserved_pos = self.bit_start_pos - 8;
129
130            // Move encoded data to its final position
131            let src_pos = self.bit_start_pos;
132            let dst_pos = reserved_pos + size_len;
133
134            if dst_pos != src_pos {
135                self.buffer
136                    .copy_within(src_pos..src_pos + encoded_bytes, dst_pos);
137            }
138
139            // Write the size
140            self.buffer[reserved_pos..reserved_pos + size_len].copy_from_slice(&var_size_buffer);
141
142            // Resize buffer to final size
143            self.buffer.resize(dst_pos + encoded_bytes, 0);
144        } else {
145            // Just resize to actual encoded bytes
146            let encoded_bytes = self.current_bit_offset.div_ceil(8);
147            self.buffer.resize(self.bit_start_pos + encoded_bytes, 0);
148        }
149    }
150
151    /// Writes the least significant `nbits` bits of a 32-bit value.
152    pub fn encode_least_significant_bits32(&mut self, nbits: u32, value: u32) -> bool {
153        if !self.bit_encoder_active {
154            return false;
155        }
156        if nbits == 0 {
157            return true;
158        }
159
160        // Pack bits efficiently into the underlying byte buffer.
161        // Bits are written LSB-first, matching Draco's EncoderBuffer.
162        let mut remaining_bits = nbits;
163        let mut v = value;
164        while remaining_bits > 0 {
165            let total_bit_offset = self.current_bit_offset;
166            let byte_offset = self.bit_start_pos + (total_bit_offset / 8);
167            let bit_shift = (total_bit_offset % 8) as u32;
168            let available = 8u32 - bit_shift;
169            let take = remaining_bits.min(available);
170            let mask = (1u32 << take) - 1;
171            let bits = v & mask;
172            self.buffer[byte_offset] |= (bits as u8) << bit_shift;
173
174            v >>= take;
175            remaining_bits -= take;
176            self.current_bit_offset += take as usize;
177        }
178        true
179    }
180
181    /// Appends a plain-old-data value in native memory representation.
182    pub fn encode<T: bytemuck::NoUninit>(&mut self, data: T) -> bool {
183        if self.bit_encoder_active {
184            return false;
185        }
186        let slice = bytemuck::bytes_of(&data);
187        self.buffer.extend_from_slice(slice);
188        true
189    }
190
191    /// Appends raw bytes.
192    pub fn encode_data(&mut self, data: &[u8]) -> bool {
193        if self.bit_encoder_active {
194            return false;
195        }
196        self.buffer.extend_from_slice(data);
197        true
198    }
199
200    /// Appends one byte.
201    pub fn encode_u8(&mut self, val: u8) {
202        self.buffer.push(val);
203    }
204
205    /// Appends a little-endian `u16`.
206    pub fn encode_u16(&mut self, val: u16) {
207        self.buffer.extend_from_slice(&val.to_le_bytes());
208    }
209
210    /// Appends a little-endian `u32`.
211    pub fn encode_u32(&mut self, val: u32) {
212        self.buffer.extend_from_slice(&val.to_le_bytes());
213    }
214
215    /// Appends a little-endian `u64`.
216    pub fn encode_u64(&mut self, val: u64) {
217        self.buffer.extend_from_slice(&val.to_le_bytes());
218    }
219
220    /// Appends an unsigned LEB128-style Draco varint.
221    pub fn encode_varint<T: Into<u64>>(&mut self, val: T) {
222        let mut v = val.into();
223        loop {
224            let mut byte = (v & 0x7F) as u8;
225            v >>= 7;
226            if v != 0 {
227                byte |= 0x80;
228                self.buffer.push(byte);
229            } else {
230                self.buffer.push(byte);
231                break;
232            }
233        }
234    }
235
236    /// Draco-compatible signed varint (ConvertSignedIntToSymbol + unsigned varint).
237    pub fn encode_varint_signed_i32(&mut self, val: i32) {
238        let symbol: u32 = if val >= 0 {
239            (val as u32) << 1
240        } else {
241            let mapped = (-(val + 1)) as u32;
242            (mapped << 1) | 1
243        };
244        self.encode_varint(symbol as u64);
245    }
246
247    /// Returns the encoded byte slice.
248    pub fn data(&self) -> &[u8] {
249        &self.buffer
250    }
251
252    /// Returns the encoded byte length.
253    pub fn size(&self) -> usize {
254        self.buffer.len()
255    }
256}