1use twizzler_abi::object::{MAX_SIZE, NULLPAGE_SIZE};
2use twizzler_rt_abi::object::ObjectHandle;
3
4pub struct SimpleBuffer {
7 handle: ObjectHandle,
8}
9
10impl core::fmt::Debug for SimpleBuffer {
11 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12 f.debug_struct("SimpleBuffer")
13 .field("id", &self.handle.id())
14 .finish_non_exhaustive()
15 }
16}
17
18impl SimpleBuffer {
19 fn ptr_to_base(&self) -> *const u8 {
20 unsafe { self.handle.start().add(NULLPAGE_SIZE) }
21 }
22
23 fn mut_ptr_to_base(&mut self) -> *mut u8 {
24 unsafe { self.handle.start().add(NULLPAGE_SIZE) }
25 }
26
27 pub fn new(handle: ObjectHandle) -> Self {
29 Self { handle }
30 }
31
32 pub fn max_len(&self) -> usize {
34 MAX_SIZE - NULLPAGE_SIZE * 2
35 }
36
37 pub fn handle(&self) -> &ObjectHandle {
39 &self.handle
40 }
41
42 pub fn into_handle(self) -> ObjectHandle {
43 self.handle
44 }
45
46 pub fn read(&self, buffer: &mut [u8]) -> usize {
49 let base_raw = self.ptr_to_base();
50 let len = core::cmp::min(buffer.len(), self.max_len());
54 let base = unsafe { core::slice::from_raw_parts(base_raw, len) };
65 (&mut buffer[0..len]).copy_from_slice(base);
66 len
67 }
68
69 pub fn read_offset(&self, buffer: &mut [u8], offset: usize) -> usize {
70 let base_raw = self.ptr_to_base();
71 if offset >= self.max_len() {
72 return 0;
73 }
74 let len = core::cmp::min(buffer.len(), self.max_len() - offset);
75 let base = unsafe { core::slice::from_raw_parts(base_raw.add(offset), len) };
76 (&mut buffer[0..len]).copy_from_slice(base);
77 len
78 }
79
80 pub fn write(&mut self, buffer: &[u8]) -> usize {
83 let base_raw = self.mut_ptr_to_base();
84 let len = core::cmp::min(buffer.len(), self.max_len());
85 let base = unsafe { core::slice::from_raw_parts_mut(base_raw, len) };
87 base.copy_from_slice(&buffer[0..len]);
88 len
89 }
90
91 pub fn write_offset(&mut self, buffer: &[u8], offset: usize) -> usize {
94 let base_raw = self.mut_ptr_to_base();
95 if offset >= self.max_len() {
96 return 0;
97 }
98 let len = core::cmp::min(buffer.len(), self.max_len() - offset);
99 let base = unsafe { core::slice::from_raw_parts_mut(base_raw.add(offset), len) };
101 base.copy_from_slice(&buffer[0..len]);
102 len
103 }
104}
105
106#[cfg(test)]
107mod test {
108 use twizzler_abi::{
109 object::Protections,
110 syscall::{sys_object_create, BackingType, LifetimeType, ObjectCreate, ObjectCreateFlags},
111 };
112 use twizzler_rt_abi::object::{MapFlags, ObjectHandle};
113
114 use super::*;
115
116 fn new_handle() -> ObjectHandle {
117 let id = sys_object_create(
118 ObjectCreate::new(
119 BackingType::Normal,
120 LifetimeType::Volatile,
121 None,
122 ObjectCreateFlags::empty(),
123 Protections::all(),
124 ),
125 &[],
126 &[],
127 )
128 .unwrap();
129
130 twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::READ | MapFlags::WRITE).unwrap()
131 }
132
133 #[test]
134 fn transfer() {
135 let obj = new_handle();
136 let mut sb = SimpleBuffer::new(obj);
137
138 let data = b"simple buffer test!";
139 let wlen = sb.write(data);
140 let mut buf = [0u8; 19];
141 assert_eq!(buf.len(), data.len());
142 assert_eq!(buf.len(), wlen);
143
144 let rlen = sb.read(&mut buf);
145 assert_eq!(rlen, wlen);
146 assert_eq!(&buf, data);
147 }
148}