Skip to main content

draco_oxide_core/buffer/
mod.rs

1use crate::safety_assert;
2pub mod attribute;
3// pub mod reader;
4// pub mod writer;
5
6use std::{alloc, fmt, ptr};
7
8pub trait OrderConfig {
9    const IS_MSB_FIRST: bool;
10}
11
12#[derive(Debug)]
13pub struct MsbFirst;
14
15#[derive(Debug)]
16pub struct LsbFirst;
17
18impl OrderConfig for MsbFirst {
19    const IS_MSB_FIRST: bool = true;
20}
21impl OrderConfig for LsbFirst {
22    const IS_MSB_FIRST: bool = false;
23}
24
25pub struct Buffer<Order: OrderConfig = MsbFirst> {
26    data: RawBuffer,
27
28    /// length of the buffer, i.e. the number of bits stored in the buffer.
29    /// The minimum number of bytes allocated for the buffer is 'len' / 8 + 1.
30    len: usize,
31
32    _phantom: std::marker::PhantomData<Order>,
33}
34
35#[allow(dead_code)]
36impl<Order: OrderConfig> Buffer<Order> {
37    /// constructs an empty buffer
38    pub fn new() -> Self {
39        Self {
40            data: RawBuffer::new(),
41            len: 0,
42            _phantom: std::marker::PhantomData,
43        }
44    }
45
46    /// A constructor that allocates the specified size (in bits) beforehand.
47    pub fn with_len(len: usize) -> Self {
48        let cap = (len + 7) >> 3;
49        let data = RawBuffer::with_capacity(cap);
50        Self {
51            data,
52            len,
53            _phantom: std::marker::PhantomData,
54        }
55    }
56
57    /// returns the number of bits stored in the buffer.
58    pub fn len(&self) -> usize {
59        self.len
60    }
61
62    /// returns the data as a slice of u8.
63    pub fn as_slice(&self) -> &[u8] {
64        // Safety: The buffer is guaranteed to be initialized with this size.
65        unsafe { std::slice::from_raw_parts(self.data.as_ptr(), (self.len + 7) >> 3) }
66    }
67}
68
69impl fmt::Debug for Buffer<MsbFirst> {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        for n in 0..(self.len + 7) >> 3 {
72            write!(f, "{:02x} ", unsafe { *self.data.as_ptr().add(n) })?;
73        }
74        write!(f, "len: {}", self.len)?;
75        Ok(())
76    }
77}
78
79struct RawBuffer {
80    data: ptr::NonNull<u8>,
81
82    /// the size of the allocation in bytes.
83    /// The number of bits that can be stored in the buffer is 'cap' * 8.
84    cap: usize,
85}
86
87impl RawBuffer {
88    fn new() -> Self {
89        Self {
90            data: ptr::NonNull::dangling(),
91            cap: 0,
92        }
93    }
94
95    /// constructs a new buffer with the given capacity.
96    /// 'cap' must be given in bytes.
97    fn with_capacity(cap: usize) -> Self {
98        let data = unsafe { alloc::alloc(alloc::Layout::array::<u8>(cap).unwrap()) };
99        Self {
100            data: ptr::NonNull::new(data).unwrap(),
101            cap,
102        }
103    }
104
105    /// expands the buffer to 'new_cap'.
106    /// Safety: 'new_cap' must be less than 'usize::Max'.
107    unsafe fn expand(&mut self, new_cap: usize) {
108        safety_assert!(new_cap < usize::MAX, "'new_cap' is too large");
109        let new_data = alloc::realloc(
110            self.data.as_ptr() as *mut u8,
111            alloc::Layout::array::<u8>(self.cap).unwrap(),
112            new_cap,
113        );
114        self.data = ptr::NonNull::new(new_data).unwrap_or_else(|| {
115            alloc::handle_alloc_error(alloc::Layout::array::<u8>(new_cap).unwrap())
116        });
117        self.cap = new_cap;
118    }
119
120    /// doubles the capacity of the buffer.
121    fn double(&mut self) {
122        let new_cap = self.cap * 2;
123        assert!(new_cap < usize::MAX, "'new_cap' is too large");
124        // Safety: Just checked that 'new_cap' is less than 'usize::Max'.
125        unsafe {
126            self.expand(new_cap);
127        }
128    }
129
130    fn as_ptr(&self) -> *mut u8 {
131        self.data.as_ptr()
132    }
133
134    fn from_vec<Data>(v: Vec<Data>) -> Self {
135        let cap = v.len() * std::mem::size_of::<Data>();
136        let data = v.as_ptr() as *mut u8;
137        // forget the value to prevent double free
138        std::mem::forget(v);
139        Self {
140            data: ptr::NonNull::new(data).unwrap(),
141            cap,
142        }
143    }
144}
145
146impl fmt::Debug for RawBuffer {
147    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148        for n in 0..self.cap {
149            write!(f, "{:02x} ", unsafe { *self.data.as_ptr().add(n) })?;
150        }
151        Ok(())
152    }
153}