pen_ffi/arc/
arc_buffer.rs1use 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}