1use core::mem;
2use core::ops::{Deref, DerefMut};
3use core::ptr::NonNull;
4
5pub(crate) struct Box<T>(NonNull<T>);
11
12impl<T> Box<T> {
13 pub fn new(value: T) -> Self {
15 let size = mem::size_of::<T>();
16 let inner = unsafe {
17 let ptr = lvgl_sys::lv_mem_alloc(size as cty::size_t) as *mut T;
18
19 assert_eq!(
21 ptr as usize % mem::align_of::<T>(),
22 0,
23 "Memory address not aligned!"
24 );
25
26 NonNull::new(ptr)
27 .map(|p| {
28 p.as_ptr().write(value);
29 p
30 })
31 .unwrap_or_else(|| {
32 panic!("Could not allocate memory {} bytes: {:?}", size, mem_info());
33 })
34 };
35 Self(inner)
36 }
37
38 pub fn into_raw(self) -> *mut T {
39 let b = mem::ManuallyDrop::new(self);
40 b.0.as_ptr()
41 }
42}
43
44impl<T> Drop for Box<T> {
45 fn drop(&mut self) {
46 unsafe {
47 lvgl_sys::lv_mem_free(self.0.as_ptr() as *mut cty::c_void);
48 }
49 }
50}
51
52impl<T> DerefMut for Box<T> {
53 fn deref_mut(&mut self) -> &mut Self::Target {
54 self.as_mut()
55 }
56}
57
58impl<T> Deref for Box<T> {
59 type Target = T;
60
61 fn deref(&self) -> &Self::Target {
62 unsafe { self.0.as_ref() }
63 }
64}
65
66impl<T> AsMut<T> for Box<T> {
67 fn as_mut(&mut self) -> &mut T {
68 unsafe { self.0.as_mut() }
69 }
70}
71
72impl<T: Clone> Clone for Box<T> {
73 fn clone(&self) -> Self {
74 unsafe { Self::new(self.0.as_ref().clone()) }
75 }
76}
77
78fn mem_info() -> lvgl_sys::lv_mem_monitor_t {
79 let mut info = lvgl_sys::lv_mem_monitor_t {
80 total_size: 0,
81 free_cnt: 0,
82 free_size: 0,
83 free_biggest_size: 0,
84 used_cnt: 0,
85 max_used: 0,
86 used_pct: 0,
87 frag_pct: 0,
88 };
89 unsafe {
90 lvgl_sys::lv_mem_monitor(&mut info as *mut _);
91 }
92 info
93}
94
95#[cfg(test)]
96mod test {
97 use super::*;
98 use crate::mem::mem_info;
99 use crate::*;
100 use std::vec::Vec;
101
102 fn teardown() {
111 unsafe {
112 lvgl_sys::lv_deinit();
113 }
114 }
115
116 #[test]
117 fn place_value_in_lv_mem() {
118 tests::initialize_test();
119
120 let v = Box::new(5);
121 drop(v);
122 let v = Box::new(10);
123 drop(v);
124
125 teardown();
126 }
127
128 #[test]
129 fn place_complex_value_in_lv_mem() {
130 tests::initialize_test();
131
132 #[repr(C)]
133 #[derive(Debug)]
134 struct Point {
135 x: u64,
136 y: i8,
137 t: i32,
138 disp: i32,
139 }
140
141 let initial_mem_info = mem_info();
142
143 let mut keep = Vec::new();
144 for i in 0..100 {
145 let p = Point {
146 x: i,
147 y: 42,
148 t: 0,
149 disp: -100,
150 };
151
152 println!("{:?}", p);
153 let mut b = Box::new(p);
154
155 println!("memory address is {:p}", b.as_mut());
156
157 let point = b.as_mut();
158 if point.x != i {
159 println!("{:?}", point);
160 }
161 assert_eq!(point.x, i);
162
163 let info = mem_info();
164 println!("mem info: {:?}", &info);
165 keep.push(b);
166 }
167 drop(keep);
168
169 let final_info = mem_info();
174 println!("mem info: {:?}", &final_info);
175
176 assert_eq!(initial_mem_info.free_size, final_info.free_size);
178
179 teardown();
180 }
181
182 #[test]
183 fn clone_object_in_lv_mem() {
184 #[cfg(feature = "unsafe_no_autoinit")]
185 crate::init();
186
187 let v1 = Box::new(5);
188 let v2 = v1.clone();
189
190 assert_eq!(*v1, *v2);
192 assert_ne!(v1.into_raw() as usize, v2.into_raw() as usize);
194 }
195}