1use ksync::{KCell, KMutex, guarded, lock};
8use pin_init::{PinInit, pin_init};
9
10pub type NameLock = ksync::RawSpinlock;
11
12#[guarded]
20#[repr(C)]
21pub struct Name<const SIZE: usize> {
22 #[mutex]
23 lock: KMutex<NameLock>,
24 #[guarded_by(lock)]
25 name: [u8; SIZE],
26}
27
28impl<const SIZE: usize> Name<SIZE> {
29 const CHECK_SIZE: () = assert!(SIZE >= 1, "Names must have SIZE >= 1");
31
32 fn copy_and_truncate(dst: &mut [u8; SIZE], name: &[u8]) {
35 let nul_idx = name.iter().position(|&b| b == 0).unwrap_or(name.len());
36 let len = nul_idx.min(SIZE - 1);
37 dst[..len].copy_from_slice(&name[..len]);
38 dst[len..].fill(0);
39 }
40
41 pub fn init() -> impl PinInit<Self, core::convert::Infallible> {
45 let () = Self::CHECK_SIZE;
46 pin_init!(Self {
47 lock <- KMutex::init(),
48 name: KCell::new([0u8; SIZE]),
49 })
50 }
51
52 pub fn len(&self) -> usize {
54 lock!(let guard = self.lock_lock());
55 let fields = guard.fields();
56 fields.name.iter().position(|&b| b == 0).unwrap_or(SIZE - 1)
57 }
58
59 pub fn is_empty(&self) -> bool {
61 self.len() == 0
62 }
63
64 pub fn get(&self, out_name: &mut [u8]) {
70 out_name.fill(0);
71 let Some((_nul, dst)) = out_name.split_last_mut() else {
72 return;
73 };
74 lock!(let guard = self.lock_lock());
75 let fields = guard.fields();
76 let nul_idx = fields.name.iter().position(|&b| b == 0).unwrap_or(SIZE - 1);
77 let copy_len = dst.len().min(nul_idx);
78 dst[..copy_len].copy_from_slice(&fields.name[..copy_len]);
79 }
80
81 pub fn set(&self, name: &[u8]) {
87 lock!(let guard = self.lock_lock());
88 let fields = guard.fields_mut();
89 Self::copy_and_truncate(fields.name, name);
90 }
91
92 pub fn set_str(&self, name: &str) {
94 self.set(name.as_bytes())
95 }
96
97 pub fn copy_name(&self) -> [u8; SIZE] {
99 let mut buf = [0u8; SIZE];
100 self.get(&mut buf);
101 buf
102 }
103
104 pub fn copy_from(&self, other: &Self) {
106 if !core::ptr::eq(self, other) {
107 let mut buf = [0u8; SIZE];
108 other.get(&mut buf);
109 self.set(&buf);
110 }
111 }
112}
113
114impl<const SIZE: usize> core::fmt::Debug for Name<SIZE> {
115 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
116 let mut buf = [0u8; SIZE];
117 self.get(&mut buf);
118 let nul_idx = buf.iter().position(|&b| b == 0).unwrap_or(SIZE);
119 let s = core::str::from_utf8(&buf[..nul_idx]).unwrap_or("<invalid utf-8>");
120 f.debug_tuple("Name").field(&s).finish()
121 }
122}