parity_scale_codec/
bit_vec.rs

1// Copyright 2019 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! `BitVec` specific serialization.
16
17use crate::{
18	codec::decode_vec_with_len, Compact, Decode, DecodeWithMemTracking, Encode, EncodeLike, Error,
19	Input, Output,
20};
21use bitvec::{
22	boxed::BitBox, order::BitOrder, slice::BitSlice, store::BitStore, vec::BitVec, view::BitView,
23};
24
25impl<O: BitOrder, T: BitStore + Encode> Encode for BitSlice<T, O> {
26	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
27		let bits = self.len();
28		assert!(
29			bits <= ARCH32BIT_BITSLICE_MAX_BITS,
30			"Attempted to encode a BitSlice with too many bits.",
31		);
32		Compact(bits as u32).encode_to(dest);
33
34		// Iterate over chunks
35		for chunk in self.chunks(core::mem::size_of::<T>() * 8) {
36			let mut element = T::ZERO;
37			element.view_bits_mut::<O>()[..chunk.len()].copy_from_bitslice(chunk);
38			element.encode_to(dest);
39		}
40	}
41}
42
43impl<O: BitOrder, T: BitStore + Encode> Encode for BitVec<T, O> {
44	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
45		self.as_bitslice().encode_to(dest)
46	}
47}
48
49impl<O: BitOrder, T: BitStore + Encode> EncodeLike for BitVec<T, O> {}
50
51/// Equivalent of `BitStore::MAX_BITS` on 32bit machine.
52const ARCH32BIT_BITSLICE_MAX_BITS: usize = 0x1fff_ffff;
53
54impl<O: BitOrder, T: BitStore + Decode> Decode for BitVec<T, O> {
55	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
56		<Compact<u32>>::decode(input).and_then(move |Compact(bits)| {
57			// Otherwise it is impossible to store it on 32bit machine.
58			if bits as usize > ARCH32BIT_BITSLICE_MAX_BITS {
59				return Err("Attempt to decode a BitVec with too many bits".into());
60			}
61			let vec = decode_vec_with_len(input, bitvec::mem::elts::<T>(bits as usize))?;
62
63			let mut result = Self::try_from_vec(vec).map_err(|_| {
64				Error::from(
65					"UNEXPECTED ERROR: `bits` is less or equal to
66					`ARCH32BIT_BITSLICE_MAX_BITS`; So BitVec must be able to handle the number of
67					segment needed for `bits` to be represented; qed",
68				)
69			})?;
70
71			assert!(bits as usize <= result.len());
72			result.truncate(bits as usize);
73			Ok(result)
74		})
75	}
76}
77
78impl<O: BitOrder, T: BitStore + Decode> DecodeWithMemTracking for BitVec<T, O> {}
79
80impl<O: BitOrder, T: BitStore + Encode> Encode for BitBox<T, O> {
81	fn encode_to<W: Output + ?Sized>(&self, dest: &mut W) {
82		self.as_bitslice().encode_to(dest)
83	}
84}
85
86impl<O: BitOrder, T: BitStore + Encode> EncodeLike for BitBox<T, O> {}
87
88impl<O: BitOrder, T: BitStore + Decode> Decode for BitBox<T, O> {
89	fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
90		Ok(BitVec::<T, O>::decode(input)?.into())
91	}
92}
93
94impl<O: BitOrder, T: BitStore + Decode> DecodeWithMemTracking for BitBox<T, O> {}
95
96#[cfg(test)]
97mod tests {
98	use super::*;
99	use crate::{codec::INITIAL_PREALLOCATION, CompactLen};
100	use bitvec::{
101		bitvec,
102		order::{Lsb0, Msb0},
103	};
104
105	macro_rules! test_data {
106		($inner_type:ident) => (
107			[
108				BitVec::<$inner_type, Msb0>::new(),
109				bitvec![$inner_type, Msb0; 0],
110				bitvec![$inner_type, Msb0; 1],
111				bitvec![$inner_type, Msb0; 0, 0],
112				bitvec![$inner_type, Msb0; 1, 0],
113				bitvec![$inner_type, Msb0; 0, 1],
114				bitvec![$inner_type, Msb0; 1, 1],
115				bitvec![$inner_type, Msb0; 1, 0, 1],
116				bitvec![$inner_type, Msb0; 0, 1, 0, 1, 0, 1, 1],
117				bitvec![$inner_type, Msb0; 0, 1, 0, 1, 0, 1, 1, 0],
118				bitvec![$inner_type, Msb0; 1, 1, 0, 1, 0, 1, 1, 0, 1],
119				bitvec![$inner_type, Msb0; 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0],
120				bitvec![$inner_type, Msb0; 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0],
121				bitvec![$inner_type, Msb0; 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0],
122				bitvec![$inner_type, Msb0; 0; 15],
123				bitvec![$inner_type, Msb0; 1; 16],
124				bitvec![$inner_type, Msb0; 0; 17],
125				bitvec![$inner_type, Msb0; 1; 31],
126				bitvec![$inner_type, Msb0; 0; 32],
127				bitvec![$inner_type, Msb0; 1; 33],
128				bitvec![$inner_type, Msb0; 0; 63],
129				bitvec![$inner_type, Msb0; 1; 64],
130				bitvec![$inner_type, Msb0; 0; 65],
131				bitvec![$inner_type, Msb0; 1; INITIAL_PREALLOCATION * 8 + 1],
132				bitvec![$inner_type, Msb0; 0; INITIAL_PREALLOCATION * 9],
133				bitvec![$inner_type, Msb0; 1; INITIAL_PREALLOCATION * 32 + 1],
134				bitvec![$inner_type, Msb0; 0; INITIAL_PREALLOCATION * 33],
135			]
136		)
137	}
138
139	#[test]
140	fn bitvec_u8() {
141		for v in &test_data!(u8) {
142			let encoded = v.encode();
143			assert_eq!(*v, BitVec::<u8, Msb0>::decode(&mut &encoded[..]).unwrap());
144
145			let elements = bitvec::mem::elts::<u8>(v.len());
146			let compact_len = Compact::compact_len(&(v.len() as u32));
147			assert_eq!(compact_len + elements, encoded.len(), "{}", v);
148		}
149	}
150
151	#[test]
152	fn bitvec_u16() {
153		for v in &test_data!(u16) {
154			let encoded = v.encode();
155			assert_eq!(*v, BitVec::<u16, Msb0>::decode(&mut &encoded[..]).unwrap());
156
157			let elements = bitvec::mem::elts::<u16>(v.len());
158			let compact_len = Compact::compact_len(&(v.len() as u32));
159			assert_eq!(compact_len + elements * 2, encoded.len(), "{}", v);
160		}
161	}
162
163	#[test]
164	fn bitvec_u32() {
165		for v in &test_data!(u32) {
166			let encoded = v.encode();
167			assert_eq!(*v, BitVec::<u32, Msb0>::decode(&mut &encoded[..]).unwrap());
168
169			let elements = bitvec::mem::elts::<u32>(v.len());
170			let compact_len = Compact::compact_len(&(v.len() as u32));
171			assert_eq!(compact_len + elements * 4, encoded.len(), "{}", v);
172		}
173	}
174
175	#[test]
176	fn bitvec_u64() {
177		for v in &test_data!(u64) {
178			let encoded = v.encode();
179			assert_eq!(*v, BitVec::<u64, Msb0>::decode(&mut &encoded[..]).unwrap());
180
181			let elements = bitvec::mem::elts::<u64>(v.len());
182			let compact_len = Compact::compact_len(&(v.len() as u32));
183			assert_eq!(compact_len + elements * 8, encoded.len(), "{}", v);
184		}
185	}
186
187	#[test]
188	fn bitslice() {
189		let data: &[u8] = &[0x69];
190		let slice = BitSlice::<u8, Msb0>::from_slice(data);
191		let encoded = slice.encode();
192		let decoded = BitVec::<u8, Msb0>::decode(&mut &encoded[..]).unwrap();
193		assert_eq!(slice, decoded.as_bitslice());
194	}
195
196	#[test]
197	fn bitbox() {
198		let data: &[u8] = &[5, 10];
199		let slice = BitSlice::<u8, Msb0>::from_slice(data);
200		let bb = BitBox::<u8, Msb0>::from_bitslice(slice);
201		let encoded = bb.encode();
202		let decoded = BitBox::<u8, Msb0>::decode(&mut &encoded[..]).unwrap();
203		assert_eq!(bb, decoded);
204	}
205
206	#[test]
207	fn bitvec_u8_encodes_as_expected() {
208		let cases = vec![
209			(bitvec![u8, Lsb0; 0, 0, 1, 1].encode(), (Compact(4u32), 0b00001100u8).encode()),
210			(bitvec![u8, Lsb0; 0, 1, 1, 1].encode(), (Compact(4u32), 0b00001110u8).encode()),
211			(bitvec![u8, Lsb0; 1, 1, 1, 1].encode(), (Compact(4u32), 0b00001111u8).encode()),
212			(bitvec![u8, Lsb0; 1, 1, 1, 1, 1].encode(), (Compact(5u32), 0b00011111u8).encode()),
213			(bitvec![u8, Lsb0; 1, 1, 1, 1, 1, 0].encode(), (Compact(6u32), 0b00011111u8).encode()),
214			(
215				bitvec![u8, Lsb0; 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1].encode(),
216				(Compact(12u32), 0b00011111u8, 0b00001011u8).encode(),
217			),
218		];
219
220		for (idx, (actual, expected)) in cases.into_iter().enumerate() {
221			assert_eq!(actual, expected, "case at index {} failed; encodings differ", idx);
222		}
223	}
224}