bitstring/
bit_length_string.rs

1use core::cmp::{
2	min,
3	Ordering,
4};
5
6use crate::{
7	bit_string::BitString,
8	FixedBitString,
9};
10
11/// Extend a
12/// [`FixedBitString`](fixed_bit_string/trait.FixedBitString.html) to a
13/// [`BitString`](bit_string/trait.BitString.html) by also storing a
14/// length.
15#[derive(Clone, Debug, Hash)]
16// TODO: drop the PartialEq + Eq manual implementations; instead require
17// the underyling type to implement sane semantics (i.e. not contain any
18// data outside what is accessible through "FixedBitString")
19#[allow(clippy::derived_hash_with_manual_eq)]
20pub struct BitLengthString<W: FixedBitString> {
21	/// underlying bit string with fixed length
22	bits: W,
23	/// current length of [`BitString`](trait.BitString.html); should
24	/// not exceed [`W::len()`](trait.FixedBitString.html#tymethod.len).
25	len: usize,
26}
27
28impl<W: FixedBitString> BitLengthString<W> {
29	/// Create new dynamic-length bit string from fixed bit string and a
30	/// length.
31	///
32	/// The bits in `bits` after `len` bits are set to false.
33	///
34	/// # Panics
35	///
36	/// Panics if `len > W::len()`.
37	pub fn new(mut bits: W, len: usize) -> Self {
38		assert!(len <= W::LEN);
39		bits.set_false_from(len);
40		BitLengthString { bits, len }
41	}
42
43	/// check whether another bit string `bits` is prefixed by `self`
44	pub fn contains(&self, bits: &W) -> bool {
45		self.bits.contains(self.len, bits)
46	}
47
48	/// get read access to the bits
49	pub fn bits(&self) -> &W {
50		&self.bits
51	}
52
53	/// length of bit string (same as
54	/// [`BitString::len()`](bit_string/trait.BitString.html#tymethod.len))
55	#[allow(clippy::len_without_is_empty)]
56	pub fn len(&self) -> usize {
57		self.len
58	}
59}
60
61impl<W: FixedBitString> BitString for BitLengthString<W> {
62	fn get(&self, ndx: usize) -> bool {
63		assert!(ndx < self.len);
64		self.bits.get(ndx)
65	}
66
67	fn set(&mut self, ndx: usize, bit: bool) {
68		assert!(ndx < self.len);
69		self.bits.set(ndx, bit);
70	}
71
72	fn flip(&mut self, ndx: usize) {
73		assert!(ndx < self.len);
74		self.bits.flip(ndx);
75	}
76
77	fn len(&self) -> usize {
78		debug_assert!(self.len <= W::LEN);
79		self.len
80	}
81
82	fn clip(&mut self, len: usize) {
83		self.bits.set_false_from(len);
84		self.len = min(self.len, len);
85	}
86
87	fn append(&mut self, bit: bool) {
88		self.bits.set(self.len, bit);
89		self.len += 1;
90	}
91
92	fn null() -> Self {
93		BitLengthString {
94			bits: W::new_all_false(),
95			len: 0,
96		}
97	}
98
99	fn shared_prefix_len(&self, other: &Self) -> usize {
100		let max_len = min(self.len, other.len);
101		min(W::shared_prefix_len(&self.bits, &other.bits), max_len)
102	}
103}
104
105impl<W: FixedBitString> Default for BitLengthString<W> {
106	fn default() -> Self {
107		Self::null()
108	}
109}
110
111impl<W: FixedBitString> Ord for BitLengthString<W> {
112	fn cmp(&self, rhs: &Self) -> Ordering {
113		self.lexicographic_cmp(rhs)
114	}
115}
116impl<W: FixedBitString> PartialOrd for BitLengthString<W> {
117	fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
118		Some(self.cmp(rhs))
119	}
120}
121
122// TODO: we derive `Hash`, so we probably could derive this too
123impl<W: FixedBitString> PartialEq for BitLengthString<W> {
124	fn eq(&self, rhs: &Self) -> bool {
125		Ordering::Equal == self.cmp(rhs)
126	}
127}
128impl<W: FixedBitString> Eq for BitLengthString<W> {}