hadris_common/types/
file.rs1use core::{fmt, ops::Range};
2
3#[derive(Clone, Copy, PartialEq, Eq)]
20pub struct FixedFilename<const N: usize> {
21 pub data: [u8; N],
22 pub len: usize,
23}
24
25impl<const N: usize> FixedFilename<N> {
26 pub const fn empty() -> Self {
27 Self {
28 data: [0; N],
29 len: 0,
30 }
31 }
32
33 pub const fn with_size(size: usize) -> Self {
34 assert!(size <= N);
35 Self {
36 data: [0; N],
37 len: size,
38 }
39 }
40
41 pub fn as_str(&self) -> &str {
42 unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
43 }
44
45 pub fn allocate(&mut self, bytes: usize) {
46 let len = self.len;
47 assert!(bytes + len <= N);
48 self.len += bytes;
49 }
51
52 pub fn as_bytes(&self) -> &[u8] {
53 &self.data[0..self.len]
54 }
55
56 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
57 &mut self.data[0..self.len]
58 }
59
60 pub fn truncate(&mut self, new_size: usize) {
61 assert!(new_size <= N);
62 self.len = new_size;
63 }
64
65 pub fn len(&self) -> usize {
66 self.len
67 }
68
69 pub fn is_empty(&self) -> bool {
70 self.len == 0
71 }
72
73 pub fn push_slice(&mut self, slice: &[u8]) -> Range<usize> {
74 assert!(self.len + slice.len() <= self.data.len());
75 let start = self.len;
76 self.len += slice.len();
77 self.data[start..self.len].copy_from_slice(slice);
78 start..self.len
79 }
80
81 pub fn push_byte(&mut self, b: u8) -> usize {
82 assert!(self.len < N);
83 self.data[self.len] = b;
84 self.len += 1;
85 self.len - 1
86 }
87
88 pub fn try_push_slice(&mut self, slice: &[u8]) -> Option<Range<usize>> {
89 if self.len + slice.len() > N {
90 return None;
91 }
92 Some(self.push_slice(slice))
93 }
94
95 pub fn try_push_byte(&mut self, b: u8) -> Option<usize> {
96 if self.len >= N {
97 return None;
98 }
99 Some(self.push_byte(b))
100 }
101
102 pub fn remaining_capacity(&self) -> usize {
103 N - self.len
104 }
105}
106
107impl<const N: usize> fmt::Debug for FixedFilename<N> {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 f.debug_tuple("FixedFilename")
110 .field(&self.as_str())
111 .finish()
112 }
113}
114
115impl<const N: usize> fmt::Display for FixedFilename<N> {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 f.write_str(self.as_str())
118 }
119}
120
121impl<const N: usize> From<&[u8]> for FixedFilename<N> {
122 fn from(value: &[u8]) -> Self {
123 assert!(value.len() <= N);
124 let mut str = FixedFilename::with_size(value.len());
125 str.data[0..value.len()].copy_from_slice(value);
126 str
127 }
128}