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