smol_bitmap/ser.rs
1//! Serialization of `SmolBitmap`.
2
3use core::{ptr, slice};
4
5use alloc::{borrow::Cow, vec::Vec};
6
7use crate::{SmolBitmap, storage::SmolBitmapBuilder};
8
9impl SmolBitmap {
10 /// Converts the bitmap to a byte slice in native-endian order.
11 ///
12 /// This method provides a view of the bitmap's internal representation
13 /// as a slice of bytes. The byte order is native-endian, meaning it
14 /// matches the endianness of the host system.
15 ///
16 /// # Safety
17 ///
18 /// The returned slice is valid as long as the bitmap is not modified.
19 /// Modifying the bitmap while holding a reference to this slice may
20 /// lead to undefined behavior.
21 ///
22 /// # Examples
23 ///
24 /// ```
25 /// use smol_bitmap::SmolBitmap;
26 ///
27 /// let mut bitmap = SmolBitmap::new();
28 /// bitmap.insert(0);
29 /// let bytes = bitmap.to_ne_bytes();
30 /// assert_eq!(bytes[0], 0b00000001);
31 /// ```
32 #[inline(always)]
33 #[must_use]
34 pub const fn to_ne_bytes(&self) -> &[u8] {
35 let slice = self.as_slice_rtrim();
36 unsafe { slice::from_raw_parts(slice.as_ptr().cast::<u8>(), slice.len() * 8) }
37 }
38
39 /// Constructs a bitmap from a byte slice in native-endian order.
40 ///
41 /// This method reads bytes in native-endian order and constructs a
42 /// [`SmolBitmap`] from them. Any remaining bytes that do not form a
43 /// complete word are returned as a separate slice.
44 ///
45 /// # Safety
46 ///
47 /// The input byte slice must be properly aligned and sized to match
48 /// the internal representation of the bitmap. Misalignment or incorrect
49 /// sizing may lead to undefined behavior.
50 #[inline(always)]
51 #[must_use]
52 pub fn from_ne_bytes(bytes: &[u8]) -> (Self, &[u8]) {
53 let (words, rest) = bytes.as_chunks::<8>();
54 let mut builder = SmolBitmapBuilder::with_capacity(words.len());
55 unsafe {
56 ptr::copy_nonoverlapping(
57 words.as_ptr().cast::<u8>(),
58 builder.as_mut_ptr().cast::<u8>(),
59 words.len() * 8,
60 );
61 builder.set_len(words.len());
62 }
63 (builder.into(), rest)
64 }
65}
66
67#[cfg(target_endian = "little")]
68impl SmolBitmap {
69 /// Converts the bitmap to little-endian bytes.
70 ///
71 /// # Examples
72 ///
73 /// ```
74 /// use smol_bitmap::SmolBitmap;
75 ///
76 /// let mut bitmap = SmolBitmap::new();
77 /// bitmap.insert(0);
78 /// bitmap.insert(7);
79 /// bitmap.insert(8);
80 ///
81 /// let bytes = bitmap.to_le_bytes();
82 /// assert_eq!(bytes[0], 0b10000001); // bits 0 and 7
83 /// assert_eq!(bytes[1], 0b00000001); // bit 8
84 /// ```
85 #[must_use]
86 pub const fn to_le_bytes(&self) -> Cow<'_, [u8]> {
87 Cow::Borrowed(self.to_ne_bytes())
88 }
89
90 /// Constructs a bitmap from little-endian bytes.
91 ///
92 /// # Examples
93 ///
94 /// ```
95 /// use smol_bitmap::SmolBitmap;
96 ///
97 /// let bytes = [0b10000001, 0b00000001, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
98 /// let (bitmap, _rest) = SmolBitmap::from_le_bytes(&bytes);
99 ///
100 /// assert!(bitmap.get(0)); // bit 0 from byte 0
101 /// assert!(bitmap.get(7)); // bit 7 from byte 0
102 /// assert!(bitmap.get(8)); // bit 0 from byte 1
103 /// ```
104 #[must_use]
105 pub fn from_le_bytes(bytes: &[u8]) -> (Self, &[u8]) {
106 Self::from_ne_bytes(bytes)
107 }
108
109 /// Converts the bitmap to big-endian bytes.
110 ///
111 /// # Examples
112 ///
113 /// ```
114 /// use smol_bitmap::SmolBitmap;
115 ///
116 /// let mut bitmap = SmolBitmap::new();
117 /// bitmap.insert(0);
118 /// bitmap.insert(7);
119 ///
120 /// let bytes = bitmap.to_be_bytes();
121 /// // Big-endian representation
122 /// ```
123 #[must_use]
124 pub fn to_be_bytes(&self) -> Cow<'_, [u8]> {
125 let slice = self.as_slice_rtrim();
126 let mut bytes = Vec::with_capacity(slice.len() * 8);
127 bytes.extend(slice.iter().flat_map(|&word| word.to_be_bytes()));
128 Cow::Owned(bytes)
129 }
130
131 /// Constructs a bitmap from big-endian bytes.
132 ///
133 /// # Examples
134 ///
135 /// ```
136 /// use smol_bitmap::SmolBitmap;
137 ///
138 /// let bytes = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]; // Big-endian representation
139 /// let (bitmap, _rest) = SmolBitmap::from_be_bytes(&bytes);
140 ///
141 /// assert!(bitmap.get(8)); // The high bit of the first byte
142 /// ```
143 #[must_use]
144 pub fn from_be_bytes(bytes: &[u8]) -> (Self, &[u8]) {
145 let (words, rest) = bytes.as_chunks::<8>();
146 let builder = words
147 .iter()
148 .map(|&w| u64::from_be_bytes(w))
149 .collect::<SmolBitmapBuilder>();
150 (builder.into(), rest)
151 }
152}
153
154#[cfg(target_endian = "big")]
155impl SmolBitmap {
156 /// Converts the bitmap to big-endian bytes.
157 ///
158 /// # Examples
159 ///
160 /// ```
161 /// use smol_bitmap::SmolBitmap;
162 ///
163 /// let mut bitmap = SmolBitmap::new();
164 /// bitmap.insert(0);
165 /// bitmap.insert(7);
166 ///
167 /// let bytes = bitmap.to_be_bytes();
168 /// // Big-endian representation
169 /// ```
170 #[must_use]
171 pub const fn to_be_bytes(&self) -> Cow<'_, [u8]> {
172 Cow::Borrowed(self.to_ne_bytes())
173 }
174
175 /// Constructs a bitmap from big-endian bytes.
176 ///
177 /// # Examples
178 ///
179 /// ```
180 /// use smol_bitmap::SmolBitmap;
181 ///
182 /// let bytes = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]; // Big-endian representation
183 /// let (bitmap, _rest) = SmolBitmap::from_be_bytes(&bytes);
184 ///
185 /// assert!(bitmap.get(8)); // The high bit of the first byte
186 /// ```
187 #[must_use]
188 pub fn from_be_bytes(bytes: &[u8]) -> (Self, &[u8]) {
189 Self::from_ne_bytes(bytes)
190 }
191
192 /// Converts the bitmap to little-endian bytes.
193 ///
194 /// # Examples
195 ///
196 /// ```
197 /// use smol_bitmap::SmolBitmap;
198 ///
199 /// let mut bitmap = SmolBitmap::new();
200 /// bitmap.insert(0);
201 /// bitmap.insert(7);
202 /// bitmap.insert(8);
203 ///
204 /// let bytes = bitmap.to_le_bytes();
205 /// assert_eq!(bytes[0], 0b10000001); // bits 0 and 7
206 /// assert_eq!(bytes[1], 0b00000001); // bit 8
207 /// ```
208 #[must_use]
209 pub fn to_le_bytes(&self) -> Cow<'_, [u8]> {
210 let slice = self.as_slice_rtrim();
211 let mut bytes = Vec::with_capacity(slice.len() * 8);
212 bytes.extend(slice.iter().flat_map(|&word| word.to_le_bytes()));
213 Cow::Owned(bytes)
214 }
215
216 /// Constructs a bitmap from little-endian bytes.
217 ///
218 /// # Examples
219 ///
220 /// ```
221 /// use smol_bitmap::SmolBitmap;
222 ///
223 /// let bytes = [0b10000001, 0b00000001, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
224 /// let (bitmap, _rest) = SmolBitmap::from_le_bytes(&bytes);
225 ///
226 /// assert!(bitmap.get(0)); // bit 0 from byte 0
227 /// assert!(bitmap.get(7)); // bit 7 from byte 0
228 /// assert!(bitmap.get(8)); // bit 0 from byte 1
229 /// ```
230 #[must_use]
231 pub fn from_le_bytes(bytes: &[u8]) -> (Self, &[u8]) {
232 let (words, rest) = bytes.as_chunks::<8>();
233 let builder = words
234 .iter()
235 .map(|&w| u64::from_le_bytes(w))
236 .collect::<SmolBitmapBuilder>();
237 (builder.into(), rest)
238 }
239}