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 read(&self, buffer: &mut [u8]) -> usize {
45 let base_raw = self.ptr_to_base();
46 let len = core::cmp::min(buffer.len(), self.max_len());
50 let base = unsafe { core::slice::from_raw_parts(base_raw, len) };
61 (&mut buffer[0..len]).copy_from_slice(base);
62 len
63 }
64
65 pub fn read_offset(&self, buffer: &mut [u8], offset: usize) -> usize {
66 let base_raw = self.ptr_to_base();
67 if offset >= self.max_len() {
68 return 0;
69 }
70 let len = core::cmp::min(buffer.len(), self.max_len() - offset);
71 let base = unsafe { core::slice::from_raw_parts(base_raw.add(offset), len) };
72 (&mut buffer[0..len]).copy_from_slice(base);
73 len
74 }
75
76 pub fn write(&mut self, buffer: &[u8]) -> usize {
79 let base_raw = self.mut_ptr_to_base();
80 let len = core::cmp::min(buffer.len(), self.max_len());
81 let base = unsafe { core::slice::from_raw_parts_mut(base_raw, len) };
83 base.copy_from_slice(&buffer[0..len]);
84 len
85 }
86
87 pub fn write_offset(&mut self, buffer: &[u8], offset: usize) -> usize {
90 let base_raw = self.mut_ptr_to_base();
91 if offset >= self.max_len() {
92 return 0;
93 }
94 let len = core::cmp::min(buffer.len(), self.max_len() - offset);
95 let base = unsafe { core::slice::from_raw_parts_mut(base_raw.add(offset), len) };
97 base.copy_from_slice(&buffer[0..len]);
98 len
99 }
100}
101
102#[cfg(test)]
103mod test {
104 use twizzler_abi::{
105 object::Protections,
106 syscall::{sys_object_create, BackingType, LifetimeType, ObjectCreate, ObjectCreateFlags},
107 };
108 use twizzler_rt_abi::object::{MapFlags, ObjectHandle};
109
110 use super::*;
111
112 fn new_handle() -> ObjectHandle {
113 let id = sys_object_create(
114 ObjectCreate::new(
115 BackingType::Normal,
116 LifetimeType::Volatile,
117 None,
118 ObjectCreateFlags::empty(),
119 Protections::all(),
120 ),
121 &[],
122 &[],
123 )
124 .unwrap();
125
126 twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::READ | MapFlags::WRITE).unwrap()
127 }
128
129 #[test]
130 fn transfer() {
131 let obj = new_handle();
132 let mut sb = SimpleBuffer::new(obj);
133
134 let data = b"simple buffer test!";
135 let wlen = sb.write(data);
136 let mut buf = [0u8; 19];
137 assert_eq!(buf.len(), data.len());
138 assert_eq!(buf.len(), wlen);
139
140 let rlen = sb.read(&mut buf);
141 assert_eq!(rlen, wlen);
142 assert_eq!(&buf, data);
143 }
144}