picky_asn1/
bit_string.rs

1use core::fmt;
2use serde::{de, ser};
3
4/// A bit string.
5///
6/// Rewrite based on [this implementation](https://melvinw.github.io/rust-asn1/asn1/struct.BitString.html) by Melvin Walls Jr.
7/// licensed with
8///
9/// > The MIT License (MIT)
10/// >
11/// > Copyright (c) 2016 Melvin Walls Jr.
12/// >
13/// > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
14/// >
15/// > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
16/// >
17/// > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18///
19/// # Examples
20///
21/// ```
22/// use picky_asn1::bit_string::BitString;
23///
24/// let mut b = BitString::with_len(60);
25///
26/// b.set(0, true);
27/// assert_eq!(b.is_set(0), true);
28///
29/// b.set(59, true);
30/// assert_eq!(b.is_set(59), true);
31///
32/// // because len is 60, attempts at setting anything greater than 59 won't change anything
33/// b.set(63, true);
34/// assert_eq!(b.is_set(63), false);
35/// ```
36#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
37pub struct BitString {
38    data: Vec<u8>,
39}
40
41impl BitString {
42    /// Returns inner bytes slice
43    pub fn as_bytes(&self) -> &[u8] {
44        &self.data
45    }
46
47    fn h_number_of_unused_bits(data_size: usize, num_bits: usize) -> u8 {
48        (data_size * 8 - num_bits) as u8
49    }
50
51    /// Construct a `BitString` of length `n` with all bits set to 0.
52    pub fn with_len(num_bits: usize) -> BitString {
53        let data_size = num_bits / 8 + if num_bits % 8 == 0 { 0 } else { 1 };
54        let mut data = vec![0x00u8; data_size + 1];
55        data[0] = Self::h_number_of_unused_bits(data_size, num_bits);
56        BitString { data }
57    }
58
59    /// Construct a `BitString` of length `n` with initial values contained in `data`.
60    ///
61    /// # Examples
62    ///
63    /// ```
64    /// use picky_asn1::bit_string::BitString;
65    ///
66    /// let v: Vec<u8> = vec![0x00, 0x02];
67    /// let b = BitString::with_bytes_and_len(v, 15);
68    /// assert_eq!(b.is_set(0), false);
69    /// assert_eq!(b.is_set(14), true);
70    ///
71    /// // because len is 15, everything greater than 14 will returns false
72    /// assert_eq!(b.is_set(15), false);
73    /// assert_eq!(b.is_set(938), false);
74    /// ```
75    pub fn with_bytes_and_len<V>(data: V, num_bits: usize) -> BitString
76    where
77        V: Into<Vec<u8>>,
78    {
79        let mut data = data.into();
80        let number_of_unused = Self::h_number_of_unused_bits(data.len(), num_bits);
81        data.insert(0, number_of_unused);
82        BitString { data }
83    }
84
85    /// Construct a `BitString` from initial values contained in `data`.
86    /// Length is inferred fromthe size of `data`.
87    ///
88    /// # Examples
89    ///
90    /// ```
91    /// use picky_asn1::bit_string::BitString;
92    ///
93    /// let v: Vec<u8> = vec![0x00, 0x02];
94    /// let b = BitString::with_bytes(v);
95    /// assert_eq!(b.is_set(0), false);
96    /// assert_eq!(b.is_set(14), true);
97    /// ```
98    pub fn with_bytes<V>(data: V) -> BitString
99    where
100        V: Into<Vec<u8>>,
101    {
102        let mut data = data.into();
103        data.insert(0, 0); // no unused bits
104        BitString { data }
105    }
106
107    /// Get the number of available bits in the `BitString`
108    pub fn get_num_bits(&self) -> usize {
109        (self.data.len() - 1) * 8 - self.data[0] as usize
110    }
111
112    /// Set the length of a `BitString` with each additional slot filled with 0.
113    ///
114    /// # Examples
115    ///
116    /// ```
117    /// use picky_asn1::bit_string::BitString;
118    ///
119    /// let v: Vec<u8> = vec![0x01, 0x01];
120    /// let mut b = BitString::with_bytes_and_len(v, 16);
121    /// assert_eq!(b.is_set(7), true);
122    /// assert_eq!(b.is_set(15), true);
123    ///
124    /// b.set_num_bits(8);
125    /// assert_eq!(b.is_set(7), true);
126    /// b.set(15, true); // attempts to set a value out of the bounds are ignored
127    /// assert_eq!(b.is_set(15), false);
128    ///
129    /// b.set_num_bits(16);
130    /// assert_eq!(b.is_set(7), true);
131    /// assert_eq!(b.is_set(15), false);
132    /// b.set(15, true);
133    /// assert_eq!(b.is_set(15), true);
134    /// ```
135    pub fn set_num_bits(&mut self, num_bits: usize) {
136        let new_size = num_bits / 8 + if num_bits % 8 == 0 { 0 } else { 1 };
137        self.data[0] = Self::h_number_of_unused_bits(new_size, num_bits);
138        self.data.resize(new_size + 1, 0);
139    }
140
141    /// Check if bit `i` is set.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// use picky_asn1::bit_string::BitString;
147    ///
148    /// let mut b = BitString::with_len(10);
149    /// assert_eq!(b.is_set(7), false);
150    /// b.set(7, true);
151    /// assert_eq!(b.is_set(7), true);
152    /// ```
153    pub fn is_set(&self, i: usize) -> bool {
154        if i > self.get_num_bits() {
155            return false;
156        }
157
158        let bucket = i / 8;
159        let pos = i - bucket * 8;
160        let mask = (1 << (7 - pos)) as u8;
161        self.data[bucket + 1] & mask != 0
162    }
163
164    /// Set bit `i` to `val`.
165    pub fn set(&mut self, i: usize, val: bool) {
166        if i > self.get_num_bits() {
167            return;
168        }
169
170        let bucket = i / 8;
171        let pos = i - bucket * 8;
172        let mask = (1 << (7 - pos)) as u8;
173
174        if val {
175            self.data[bucket + 1] |= mask;
176        } else {
177            self.data[bucket + 1] &= !mask;
178        }
179    }
180
181    pub fn get_num_unused_bits(&self) -> u8 {
182        self.data[0]
183    }
184
185    pub fn get_num_buckets(&self) -> usize {
186        self.data.len() - 1
187    }
188
189    pub fn get_bucket(&self, i: usize) -> u8 {
190        self.data[i + 1]
191    }
192
193    pub fn get_bucket_mut(&mut self, i: usize) -> &mut u8 {
194        &mut self.data[i + 1]
195    }
196
197    pub fn set_bucket(&mut self, i: usize, value: u8) {
198        self.data[i + 1] = value
199    }
200
201    /// Returns an immutabe view on the payload.
202    ///
203    /// # Examples
204    ///
205    /// ```
206    /// use picky_asn1::bit_string::BitString;
207    ///
208    /// let v: Vec<u8> = vec![0x01, 0x00];
209    /// let mut b = BitString::with_bytes_and_len(v, 15);
210    /// b.set(14, true);
211    /// let payload = b.payload_view();
212    /// assert_eq!(payload, &[0x01, 0x02]);
213    /// ```
214    pub fn payload_view(&self) -> &[u8] {
215        &self.data[1..]
216    }
217
218    /// Returns a mutabe view on the payload.
219    ///
220    /// # Examples
221    ///
222    /// ```
223    /// use picky_asn1::bit_string::BitString;
224    ///
225    /// let v: Vec<u8> = vec![0x01, 0x00];
226    /// let mut b = BitString::with_bytes_and_len(v, 15);
227    /// b.set(14, true);
228    /// let payload = b.payload_view_mut();
229    /// payload[0] = 0x20;
230    /// assert_eq!(payload, &[0x20, 0x02]);
231    /// ```
232    pub fn payload_view_mut(&mut self) -> &mut [u8] {
233        &mut self.data[1..]
234    }
235}
236
237impl fmt::Debug for BitString {
238    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239        write!(f, "0x")?;
240        self.data.iter().try_for_each(|byte| write!(f, "{byte:02X}"))?;
241        Ok(())
242    }
243}
244
245impl From<BitString> for Vec<u8> {
246    /// Strips 'unused bits count' byte and returns payload.
247    ///
248    /// # Examples
249    ///
250    /// ```
251    /// use picky_asn1::bit_string::BitString;
252    ///
253    /// let v: Vec<u8> = vec![0x01, 0x00];
254    /// let mut b = BitString::with_bytes_and_len(v, 15);
255    /// b.set(14, true);
256    /// let payload: Vec<u8> = b.into();
257    /// assert_eq!(payload, vec![0x01, 0x02]);
258    /// ```
259    fn from(mut bs: BitString) -> Self {
260        bs.data.drain(1..).collect()
261    }
262}
263
264impl<'de> de::Deserialize<'de> for BitString {
265    fn deserialize<D>(deserializer: D) -> Result<BitString, D::Error>
266    where
267        D: de::Deserializer<'de>,
268    {
269        struct Visitor;
270
271        impl<'de> de::Visitor<'de> for Visitor {
272            type Value = BitString;
273
274            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
275                formatter.write_str("a valid buffer representing a bit string")
276            }
277
278            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
279            where
280                E: de::Error,
281            {
282                self.visit_byte_buf(v.to_vec())
283            }
284
285            fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
286            where
287                E: de::Error,
288            {
289                Ok(BitString { data: v })
290            }
291        }
292
293        deserializer.deserialize_byte_buf(Visitor)
294    }
295}
296
297impl ser::Serialize for BitString {
298    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
299    where
300        S: ser::Serializer,
301    {
302        serializer.serialize_bytes(&self.data)
303    }
304}
305
306impl Default for BitString {
307    fn default() -> Self {
308        BitString::with_len(0)
309    }
310}