pen_ffi/arc/
arc_buffer.rs

1use super::arc_block::ArcBlock;
2use core::{alloc::Layout, slice};
3
4#[derive(Debug)]
5#[repr(C)]
6pub struct ArcBuffer {
7    block: ArcBlock,
8}
9
10#[repr(C)]
11struct ArcBufferInner {
12    length: usize,
13    first_byte: u8,
14}
15
16impl ArcBuffer {
17    pub fn new(length: usize) -> Self {
18        Self {
19            block: if length == 0 {
20                ArcBlock::new(Layout::from_size_align(0, 1).unwrap())
21            } else {
22                let mut block = ArcBlock::new(
23                    Layout::new::<usize>()
24                        .extend(Layout::array::<u8>(length).unwrap())
25                        .unwrap()
26                        .0
27                        .pad_to_align(),
28                );
29
30                unsafe { *(block.ptr_mut() as *mut usize) = length }
31
32                block
33            },
34        }
35    }
36
37    pub fn as_slice(&self) -> &[u8] {
38        unsafe {
39            if self.block.is_null() {
40                slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0)
41            } else {
42                let inner = &*(self.block.ptr() as *const ArcBufferInner);
43
44                slice::from_raw_parts(&inner.first_byte, inner.length)
45            }
46        }
47    }
48
49    pub fn as_slice_mut(&mut self) -> &mut [u8] {
50        unsafe {
51            if self.block.is_null() {
52                slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0)
53            } else {
54                let inner = &mut *(self.block.ptr() as *mut ArcBufferInner);
55
56                slice::from_raw_parts_mut(&mut inner.first_byte, inner.length)
57            }
58        }
59    }
60}
61
62impl Default for ArcBuffer {
63    fn default() -> Self {
64        Self::new(0)
65    }
66}
67
68impl Clone for ArcBuffer {
69    fn clone(&self) -> Self {
70        Self {
71            block: self.block.clone(),
72        }
73    }
74}
75
76impl Drop for ArcBuffer {
77    fn drop(&mut self) {
78        self.block.drop::<()>();
79    }
80}
81
82impl From<&[u8]> for ArcBuffer {
83    fn from(slice: &[u8]) -> Self {
84        let mut buffer = Self::new(slice.len());
85
86        buffer.as_slice_mut().copy_from_slice(slice);
87
88        buffer
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use alloc::vec;
96
97    fn drop<T>(_: T) {}
98
99    #[test]
100    fn create_buffer() {
101        ArcBuffer::new(42);
102    }
103
104    #[test]
105    fn create_empty() {
106        ArcBuffer::new(0);
107    }
108
109    #[test]
110    fn clone() {
111        let arc = ArcBuffer::new(42);
112        drop(arc.clone());
113        drop(arc);
114    }
115
116    #[test]
117    fn convert_from_vec() {
118        let _ = ArcBuffer::from(vec![0u8; 42].as_slice());
119    }
120
121    #[test]
122    fn convert_from_string() {
123        let _ = ArcBuffer::from("hello".as_bytes());
124    }
125}