bit_byte_bit/
scheme.rs

1use std::collections::HashMap;
2use std::fmt::{Debug};
3use std::hash::Hash;
4use crate::{Bits};
5
6
7/// Defines a region of bits.
8///
9/// Each field has a unit, size, and a flag indicating if the field represents a signed integer.
10/// The unit is the minimum number of bits extracted by the field. The size is the total number
11/// of units extracted by the field.
12///
13/// The flag comes into play when a field extracts more bits than are available. If at least one
14/// bit is still available and the flag is true, the bit string is sign extended to the length of
15/// the field.
16/// 
17/// ## Constants
18///
19/// Common field types.
20///
21/// |   Constant    | Unit |   Size  | Signed |
22/// |:-------------:|:----:|:-------:|:------:|
23/// | `BIT`         |  1   |    1    |
24/// | `BYTES`       |  8   | UNBOUND |
25/// | `SIGNED`      |  1   | UNBOUND |   X
26/// | `SIGNED_2`    |  1   |    2    |   X
27/// | `SIGNED_4`    |  1   |    4    |   X
28/// | `SIGNED_8`    |  1   |    8    |   X
29/// | `SIGNED_16`   |  1   |    16   |   X
30/// | `SIGNED_32`   |  1   |    32   |   X
31/// | `SIGNED_64`   |  1   |    64   |   X
32/// | `UNSIGNED`    |  1   | UNBOUND |
33/// | `UNSIGNED_2`  |  1   |    2    |
34/// | `UNSIGNED_4`  |  1   |    4    |
35/// | `UNSIGNED_8`  |  1   |    8    |
36/// | `UNSIGNED_16` |  1   |    16   |
37/// | `UNSIGNED_32` |  1   |    32   |
38/// | `UNSIGNED_64` |  1   |    64   |
39///
40#[derive(Debug, Copy, Clone)]
41pub struct Field {
42    size: isize,
43    unit: usize,
44    signed: bool
45}
46
47impl Field {
48    pub const BIT: Field = Field { size: 1, unit: 1, signed: false };
49    pub const BYTES: Field = Field { size: -1, unit: 8, signed: false };
50    pub const SIGNED: Field = Field { size: -1, unit: 1, signed: true };
51    pub const SIGNED_2: Field = Field { size: 2, unit: 1, signed: true };
52    pub const SIGNED_4: Field = Field { size: 4, unit: 1, signed: true };
53    pub const SIGNED_8: Field = Field { size: 8, unit: 1, signed: true };
54    pub const SIGNED_16: Field = Field { size: 16, unit: 1, signed: true };
55    pub const SIGNED_32: Field = Field { size: 32, unit: 1, signed: true };
56    pub const SIGNED_64: Field = Field { size: 64, unit: 1, signed: true };
57    pub const UNSIGNED: Field = Field { size: -1, unit: 1, signed: false };
58    pub const UNSIGNED_2: Field = Field { size: 2, unit: 1, signed: false };
59    pub const UNSIGNED_4: Field = Field { size: 4, unit: 1, signed: false };
60    pub const UNSIGNED_8: Field = Field { size: 8, unit: 1, signed: false };
61    pub const UNSIGNED_16: Field = Field { size: 16, unit: 1, signed: false };
62    pub const UNSIGNED_32: Field = Field { size: 32, unit: 1, signed: false };
63    pub const UNSIGNED_64: Field = Field { size: 64, unit: 1, signed: false };
64
65    /// Bit field aligned to a given unit
66    ///
67    /// When `m` and `n` are negative `Bits::aligned(m, signed) == Bits::aligned(n, signed)`,
68    /// even if `m != n`.
69    ///
70    /// Example
71    /// ```
72    /// # use bit_byte_bit::{Field};
73    /// let field = Field::aligned(7, 48, false);
74    ///
75    /// assert_eq!(field.unit(), 7);
76    /// assert_eq!(field.size(), 48);
77    /// assert_eq!(field.len(), 48 * 7);
78    ///
79    /// let mfield = Field::aligned(7, -1, true);
80    /// let nfield = Field::aligned(7, isize::MIN, true);
81    ///
82    /// assert_eq!(mfield, nfield);
83    /// assert_eq!(mfield.size(), -1);
84    /// assert_eq!(nfield.size(), -1);
85    /// assert!(mfield.is_signed());
86    /// ```
87    pub fn aligned(unit: usize, size: isize, signed: bool) -> Self { Field { size, unit, signed } }
88
89    /// Byte-aligned bit field
90    ///
91    /// When `m` and `n` are negative `Bits::bytes(m, signed) == Bits::bytes(n, signed)`,
92    /// even if `m != n`.
93    ///
94    /// Example
95    /// ```
96    /// # use bit_byte_bit::{Field};
97    /// let field = Field::bytes(48, false);
98    ///
99    /// assert_eq!(field.unit(), 8);
100    /// assert_eq!(field.size(), 48);
101    /// assert_eq!(field.len(), 48 * 8);
102    ///
103    /// let mfield = Field::bytes(-1, true);
104    /// let nfield = Field::bytes(isize::MIN, true);
105    ///
106    /// assert_eq!(mfield, nfield);
107    /// assert_eq!(mfield.size(), -1);
108    /// assert_eq!(nfield.size(), -1);
109    /// assert!(mfield.is_signed());
110    /// ```
111    pub fn bytes(size: isize, signed: bool) -> Self { Field { size, unit: 8, signed } }
112
113    /// Bit field
114    ///
115    /// When `m` and `n` are negative `Bits::bits(m, signed) == Bits::bits(n, signed)`,
116    /// even if `m != n`.
117    ///
118    /// Example
119    /// ```
120    /// # use bit_byte_bit::{Field};
121    /// let field = Field::signed(96);
122    ///
123    /// assert_eq!(field.unit(), 1);
124    /// assert_eq!(field.size(), 96);
125    /// assert_eq!(field.len(), 96);
126    /// assert!(field.is_signed());
127    ///
128    /// let mfield = Field::signed(-1);
129    /// let nfield = Field::signed(isize::MIN);
130    ///
131    /// assert_eq!(mfield, nfield);
132    /// assert_eq!(mfield.size(), -1);
133    /// assert_eq!(nfield.size(), -1);
134    /// assert!(mfield.is_signed());
135    ///
136    /// ```
137    pub fn signed(size: isize) -> Self { Field { size, unit: 1, signed: true } }
138
139    /// Bit field
140    ///
141    /// When `m` and `n` are negative `Bits::bits(m, signed) == Bits::bits(n, signed)`,
142    /// even if `m != n`.
143    ///
144    /// Example
145    /// ```
146    /// # use bit_byte_bit::{Field};
147    /// let field = Field::unsigned(96);
148    ///
149    /// assert_eq!(field.unit(), 1);
150    /// assert_eq!(field.size(), 96);
151    /// assert_eq!(field.len(), 96);
152    /// assert!(!field.is_signed());
153    ///
154    /// let mfield = Field::unsigned(-1);
155    /// let nfield = Field::unsigned(isize::MIN);
156    ///
157    /// assert_eq!(mfield, nfield);
158    /// assert_eq!(mfield.size(), -1);
159    /// assert_eq!(nfield.size(), -1);
160    /// assert!(!mfield.is_signed());
161    ///
162    /// ```
163    pub fn unsigned(size: isize) -> Self { Field { size, unit: 1, signed: false } }
164
165    /// Whether this field represents a signed integer.
166    ///
167    /// Example
168    /// ```
169    /// # use bit_byte_bit::{Field};
170    /// assert!(Field::aligned(7, 48, true).is_signed());
171    /// assert!(!Field::aligned(7, 48, false).is_signed());
172    /// assert!(Field::bytes(-1, true).is_signed());
173    /// assert!(!Field::bytes(-1, false).is_signed());
174    /// assert!(Field::signed(96).is_signed());
175    /// assert!(!Field::unsigned(96).is_signed());
176    /// ```
177    pub fn is_signed(&self) -> bool { self.signed }
178
179    /// Number of bits extracted by the field
180    ///
181    /// `-1` means that the field extracts the maximum number of bits that can be divided by the
182    /// `unit` of the field. Extraction never exceeds the remaining the number of bits.
183    ///
184    /// Example
185    /// ```
186    /// # use bit_byte_bit::{Field};
187    /// assert_eq!(Field::aligned(0, -1, true).len(), 0);
188    /// assert_eq!(Field::aligned(7, 0, false).len(), 0);
189    /// assert_eq!(Field::aligned(7, 48, true).len(), 48 * 7);
190    /// assert_eq!(Field::aligned(7, -1, false).len(), -1);
191    /// assert_eq!(Field::aligned(7, isize::MIN, true).len(), -1);
192    /// assert_eq!(Field::bytes(48, true).len(), 48 * 8);
193    /// assert_eq!(Field::bytes(-1, false).len(), -1);
194    /// assert_eq!(Field::bytes(isize::MIN, true).len(), -1);
195    /// assert_eq!(Field::signed(48).len(), 48);
196    /// assert_eq!(Field::signed(-1).len(), -1);
197    /// assert_eq!(Field::signed(isize::MIN).len(), -1);
198    /// assert_eq!(Field::unsigned(48).len(), 48);
199    /// assert_eq!(Field::unsigned(-1).len(), -1);
200    /// assert_eq!(Field::unsigned(isize::MIN).len(), -1);
201    /// ```
202    pub fn len(&self) -> isize {
203        match (self.size, self.unit) {
204            (0, _) | (_, 0) => 0,
205            (size, _) if size < 0 => -1,
206            (size, unit) => size * (unit as isize)
207        }
208    }
209
210    /// Number of units in the field
211    ///
212    /// Example
213    /// ```
214    /// # use bit_byte_bit::{Field};
215    /// assert_eq!(Field::aligned(7, 48, true).size(), 48);
216    /// assert_eq!(Field::aligned(7, -1, false).size(), -1);
217    /// assert_eq!(Field::aligned(7, isize::MIN, true).size(), -1);
218    /// assert_eq!(Field::bytes(48, true).size(), 48);
219    /// assert_eq!(Field::bytes(-1, false).size(), -1);
220    /// assert_eq!(Field::bytes(isize::MIN, true).size(), -1);
221    /// assert_eq!(Field::signed(48).size(), 48);
222    /// assert_eq!(Field::signed(-1).size(), -1);
223    /// assert_eq!(Field::signed(isize::MIN).size(), -1);
224    /// assert_eq!(Field::unsigned(48).size(), 48);
225    /// assert_eq!(Field::unsigned(-1).size(), -1);
226    /// assert_eq!(Field::unsigned(isize::MIN).size(), -1);
227    /// ```
228    pub fn size(&self) -> isize { if self.size < 0 { -1 } else { self.size } }
229
230    /// Minimum number of bits extracted by the field.
231    ///
232    /// Example
233    /// ```
234    /// # use bit_byte_bit::{Field};
235    /// assert_eq!(Field::aligned(7, 48, true).unit(), 7);
236    /// assert_eq!(Field::aligned(7, -1, false).unit(), 7);
237    /// assert_eq!(Field::aligned(7, isize::MIN, true).unit(), 7);
238    /// assert_eq!(Field::bytes(48, true).unit(), 8);
239    /// assert_eq!(Field::bytes(-1, false).unit(), 8);
240    /// assert_eq!(Field::bytes(isize::MIN, true).unit(), 8);
241    /// assert_eq!(Field::signed(48).unit(), 1);
242    /// assert_eq!(Field::signed(-1).unit(), 1);
243    /// assert_eq!(Field::signed(isize::MIN).unit(), 1);
244    /// assert_eq!(Field::unsigned(48).unit(), 1);
245    /// assert_eq!(Field::unsigned(-1).unit(), 1);
246    /// assert_eq!(Field::unsigned(isize::MIN).unit(), 1);
247    /// ```
248    pub fn unit(&self) -> usize { self.unit }
249
250    fn default(&self) -> Bits {
251        let length = self.len();
252
253        if length <= 0 {
254            Bits::empty()
255        } else {
256            Bits::zeros(length as usize)
257        }
258    }
259
260    fn extract(&self, bits: &Bits, bits_len: usize, start: usize) -> Bits {
261        let length = self.len();
262
263        if length == 0 { return Bits::empty() }
264
265        if length < 0 { return self.extract_var_data(bits, bits_len, start); }
266
267        let length = length as usize;
268        let end = start + length;
269
270        if end > bits_len {
271            let x_len = bits_len - start;
272
273            let mut remaining_bits = Bits::take(bits.bytes(), start, x_len);
274            let signed = self.signed && remaining_bits.i(x_len - 1) == 1;
275
276            remaining_bits.push_left(signed, end - bits_len);
277
278            remaining_bits
279        } else {
280            Bits::take(bits.bytes(), start, length)
281        }
282    }
283
284    fn extract_var_data(&self, bits: &Bits, bits_len: usize, start: usize) -> Bits {
285        let remaining = bits_len - start;
286
287        Bits::take(bits.bytes(), start, remaining - (remaining % self.unit))
288    }
289}
290
291impl Eq for Field {}
292
293impl PartialEq for Field {
294    fn eq(&self, other: &Field) -> bool {
295            self.unit == other.unit
296            && self.signed == other.signed
297            && ((self.size < 0 && other.size < 0) || (self.size == other.size))
298    }
299}
300
301
302/// Defines a pattern giving meaning to different regions of a bit string.
303pub struct Scheme(Vec<Field>);
304
305impl Scheme {
306    /// # Example
307    /// ```
308    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
309    ///
310    /// let unsigned_3 = Field::unsigned(3);
311    ///
312    /// let scheme = Scheme::new([
313    ///     Field::signed(5),
314    ///     Field::BIT,
315    ///     unsigned_3,
316    ///     unsigned_3,
317    ///     Field::UNSIGNED_4,
318    ///     Field::aligned(23, 1, true),
319    ///     Field::unsigned(32),
320    ///     Field::signed(32),
321    ///     Field::bytes(4, false),
322    ///     Field::aligned(6, 8, true)
323    /// ]);
324    ///
325    /// let time_since_epoch = Field::UNSIGNED_64;
326    /// let identifier = Field::UNSIGNED_8;
327    /// let datatype = Field::UNSIGNED_4;
328    /// let data = Field::BYTES;
329    ///
330    /// let scheme2 = Scheme::new([time_since_epoch, identifier, datatype, data]);
331    /// ```
332    pub fn new<I: IntoIterator<Item = Field>>(pattern: I) -> Self {
333        Scheme(pattern.into_iter().collect())
334    }
335
336    /// Number of bits extracted
337    ///
338    /// If any field in the scheme has a negative length, this method returns -1, indicating
339    /// the scheme extracts a variable number of bits.
340    ///
341    /// # Example
342    /// ```
343    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
344    ///
345    /// let unsigned_3 = Field::unsigned(3);
346    ///
347    /// let scheme = Scheme::new([
348    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
349    /// ]);
350    ///
351    /// assert_eq!(scheme.len(), 16);
352    ///
353    /// let scheme2 = Scheme::new([
354    ///     Field::aligned(23, 1, true),
355    ///     Field::unsigned(0),
356    ///     Field::unsigned(32),
357    ///     Field::bytes(4, false),
358    ///     Field::aligned(0, 8, false),
359    ///     Field::aligned(7, 8, true)
360    /// ]);
361    ///
362    /// let scheme3 = Scheme::new([
363    ///     Field::aligned(23, 1, true),
364    ///     Field::unsigned(0),
365    ///     Field::unsigned(32),
366    ///     Field::signed(-1),
367    ///     Field::bytes(4, false),
368    ///     Field::aligned(0, 8, false),
369    ///     Field::aligned(7, 8, true)
370    /// ]);
371    ///
372    /// assert_eq!(scheme3.len(), -1);
373    /// ```
374    pub fn len(&self) -> isize {
375        let mut acc = 0;
376
377        for field in &self.0 {
378            let n = field.len();
379
380            if n < 0 { return -1; }
381
382            acc += n
383        }
384
385        acc
386    }
387
388    /// Extracts the data associated with the fields of this scheme, associating each with a key.
389    ///
390    /// # Example
391    /// ```
392    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
393    ///
394    /// let unsigned_3 = Field::unsigned(3);
395    ///
396    /// let scheme = Scheme::new([
397    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
398    /// ]);
399    ///
400    /// let bits = Bits::new([0xBA, 0x1C]);
401    ///
402    /// let parts = scheme.extract_from_bits(
403    ///     &bits,
404    ///     ["opcode", "flag", "destination_register", "source_register", "constant"]
405    /// );
406    ///
407    /// assert_eq!(bits_as::int8(&parts["opcode"]), -6);
408    /// assert_eq!(bits_as::uint8(&parts["flag"]), 1);
409    /// assert_eq!(bits_as::uint8(&parts["destination_register"]), 2);
410    /// assert_eq!(bits_as::uint8(&parts["source_register"]), 6);
411    /// assert_eq!(bits_as::uint8(&parts["constant"]), 1);
412    ///
413    /// let bits = Bits::new([0xBA]);
414    ///
415    /// let parts = scheme.extract_from_bits(
416    ///     &bits,
417    ///     ["opcode", "flag", "destination_register", "source_register", "constant"]
418    /// );
419    ///
420    /// assert_eq!(bits_as::int8(&parts["opcode"]), -6);
421    /// assert_eq!(bits_as::uint8(&parts["flag"]), 1);
422    /// assert_eq!(bits_as::uint8(&parts["destination_register"]), 2);
423    /// assert_eq!(bits_as::uint8(&parts["source_register"]), 0);
424    /// assert_eq!(bits_as::uint8(&parts["constant"]), 0);
425    /// ```
426    pub fn extract_from_bits<K, I>(&self, bits: &Bits, keys: I) -> HashMap<K, Bits>
427    where K: Eq + Hash, I: IntoIterator<Item=K> {
428        keys.into_iter().zip(self.split_bits_at(0, bits)).collect()
429    }
430
431    /// Extracts the data associated with the fields of this scheme.
432    ///
433    /// # Example
434    /// ```
435    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
436    ///
437    /// let unsigned_3 = Field::unsigned(3);
438    ///
439    /// let scheme = Scheme::new([
440    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
441    /// ]);
442    ///
443    /// let bits = Bits::new([0xBA, 0x1C]);
444    ///
445    /// let parts = scheme.extract_from_bits_at(
446    ///     0,
447    ///     &bits,
448    ///     ["opcode", "flag", "destination_register", "source_register", "constant"]
449    /// );
450    ///
451    /// assert_eq!(bits_as::int8(&parts["opcode"]), -6);
452    /// assert_eq!(bits_as::uint8(&parts["flag"]), 1);
453    /// assert_eq!(bits_as::uint8(&parts["destination_register"]), 2);
454    /// assert_eq!(bits_as::uint8(&parts["source_register"]), 6);
455    /// assert_eq!(bits_as::uint8(&parts["constant"]), 1);
456    ///
457    /// let parts = scheme.extract_from_bits_at(
458    ///     8,
459    ///     &bits,
460    ///     ["opcode", "flag", "destination_register", "source_register", "constant"]
461    /// );
462    ///
463    /// assert_eq!(bits_as::int8(&parts["opcode"]), -4);
464    /// assert_eq!(bits_as::uint8(&parts["flag"]), 0);
465    /// assert_eq!(bits_as::uint8(&parts["destination_register"]), 0);
466    /// assert_eq!(bits_as::uint8(&parts["source_register"]), 0);
467    /// assert_eq!(bits_as::uint8(&parts["constant"]), 0);
468    /// ```
469    pub fn extract_from_bits_at<K, I>(&self, index: usize, bits: &Bits, keys: I) -> HashMap<K, Bits>
470    where K: Eq + Hash, I: IntoIterator<Item=K> {
471        keys.into_iter().zip(self.split_bits_at(index, bits)).collect()
472    }
473
474    /// Extracts the data associated with the fields of this scheme
475    ///
476    /// # Example
477    /// ```
478    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
479    ///
480    /// let unsigned_3 = Field::unsigned(3);
481    ///
482    /// let scheme = Scheme::new([
483    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
484    /// ]);
485    ///
486    /// let parts = scheme.extract_from_bytes(
487    ///     [0xBA, 0x1C],
488    ///     ["opcode", "flag", "destination_register", "source_register", "constant"]
489    /// );
490    ///
491    /// assert_eq!(bits_as::int8(&parts["opcode"]), -6);
492    /// assert_eq!(bits_as::uint8(&parts["flag"]), 1);
493    /// assert_eq!(bits_as::uint8(&parts["destination_register"]), 2);
494    /// assert_eq!(bits_as::uint8(&parts["source_register"]), 6);
495    /// assert_eq!(bits_as::uint8(&parts["constant"]), 1);
496    ///
497    /// let parts = scheme.extract_from_bytes(
498    ///     [0xBA],
499    ///     ["opcode", "flag", "destination_register", "source_register", "constant"]
500    /// );
501    /// ```
502    pub fn extract_from_bytes<K, IB, IK>(&self, bytes: IB, keys: IK) -> HashMap<K, Bits>
503    where K: Eq + Hash, IB: IntoIterator<Item=u8>, IK: IntoIterator<Item=K> {
504        keys.into_iter().zip(self.split_bytes_at(0, bytes)).collect()
505    }
506
507    /// Extracts the data associated with the fields of this scheme.
508    ///
509    /// # Example
510    /// ```
511    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
512    ///
513    /// let unsigned_3 = Field::unsigned(3);
514    ///
515    /// let scheme = Scheme::new([
516    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
517    /// ]);
518    ///
519    /// let parts = scheme.extract_from_bytes_at(
520    ///     0,
521    ///     [0xBA, 0x1C],
522    ///     ["opcode", "flag", "destination_register", "source_register", "constant"]
523    /// );
524    ///
525    /// assert_eq!(bits_as::int8(&parts["opcode"]), -6);
526    /// assert_eq!(bits_as::uint8(&parts["flag"]), 1);
527    /// assert_eq!(bits_as::uint8(&parts["destination_register"]), 2);
528    /// assert_eq!(bits_as::uint8(&parts["source_register"]), 6);
529    /// assert_eq!(bits_as::uint8(&parts["constant"]), 1);
530    ///
531    /// let parts = scheme.extract_from_bytes_at(
532    ///     8,
533    ///     [0xBA, 0x1C],
534    ///     ["opcode", "flag", "destination_register", "source_register", "constant"]
535    /// );
536    ///
537    /// assert_eq!(bits_as::int8(&parts["opcode"]), -4);
538    /// assert_eq!(bits_as::uint8(&parts["flag"]), 0);
539    /// assert_eq!(bits_as::uint8(&parts["destination_register"]), 0);
540    /// assert_eq!(bits_as::uint8(&parts["source_register"]), 0);
541    /// assert_eq!(bits_as::uint8(&parts["constant"]), 0);
542    /// ```
543    pub fn extract_from_bytes_at<K, IB, IK>(
544        &self,
545        index: usize,
546        bytes: IB,
547        keys: IK
548    ) -> HashMap<K, Bits>
549    where K: Eq + Hash, IB: IntoIterator<Item=u8>, IK: IntoIterator<Item=K> {
550        keys.into_iter().zip(self.split_bytes_at(index, bytes)).collect()
551    }
552    
553    /// Extracts the data associated with the fields of this scheme
554    ///
555    /// # Example
556    /// ```
557    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
558    ///
559    /// let unsigned_3 = Field::unsigned(3);
560    ///
561    /// let scheme = Scheme::new([
562    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
563    /// ]);
564    ///
565    /// let bits = Bits::new([0xBA, 0x1C]);
566    /// let parts = scheme.split_bits(&bits);
567    ///
568    /// assert_eq!(bits_as::int8(&parts[0]), -6);
569    /// assert_eq!(bits_as::uint8(&parts[1]), 1);
570    /// assert_eq!(bits_as::uint8(&parts[2]), 2);
571    /// assert_eq!(bits_as::uint8(&parts[3]), 6);
572    /// assert_eq!(bits_as::uint8(&parts[4]), 1);
573    ///
574    /// let bits2 = Bits::new([0xBA]);
575    /// let parts2 = scheme.split_bits(&bits2);
576    ///
577    /// assert_eq!(bits_as::int8(&parts2[0]), -6);
578    /// assert_eq!(bits_as::uint8(&parts2[1]), 1);
579    /// assert_eq!(bits_as::uint8(&parts2[2]), 2);
580    /// assert_eq!(bits_as::uint8(&parts2[3]), 0);
581    /// assert_eq!(bits_as::uint8(&parts2[4]), 0);
582    ///
583    /// let scheme2 = Scheme::new([
584    ///     Field::aligned(23, -1, true),
585    ///     Field::aligned(0, -1, false),
586    ///     Field::bytes(-1, false),
587    ///     Field::signed(-1),
588    ///     Field::unsigned(-1),
589    ///     Field::unsigned(0),
590    ///     Field::unsigned(32),
591    ///     Field::bytes(4, false),
592    ///     Field::aligned(0, 8, false),
593    ///     Field::aligned(7, 8, true),
594    ///     Field::signed(-1),
595    ///     Field::unsigned(-1)
596    /// ]);
597    ///
598    /// let bytes = [0xBA, 0xDC, 0xFE, 0x10, 0x32];
599    /// let bits3 = Bits::from(bytes.as_slice()); // 38-bits
600    /// let parts = scheme2.split_bits(&bits3);
601    ///
602    /// assert_eq!(bits_as::int32(&parts[0]), 0xFFFEDCBAu32 as i32);
603    /// assert_eq!(parts[1], Bits::empty());
604    /// assert_eq!(bits_as::vec_u8(&parts[2]), vec![0x21]);
605    /// assert_eq!(bits_as::vec_i32(&parts[3]), vec![-28]);
606    /// assert_eq!(parts[4], Bits::empty());
607    /// assert_eq!(parts[5], Bits::empty());
608    /// assert_eq!(parts[6], Bits::zeros(32));
609    /// assert_eq!(parts[7], Bits::zeros(32));
610    /// assert_eq!(parts[8], Bits::empty());
611    /// assert_eq!(parts[9], Bits::zeros(56));
612    /// assert_eq!(parts[10], Bits::empty());
613    /// assert_eq!(parts[11], Bits::empty());
614    /// ```
615    pub fn split_bits(&self, bits: &Bits) -> Vec<Bits> { self.split_bits_at(0, bits) }
616
617    /// Extracts the data associated with the fields of this scheme.
618    ///
619    /// # Example
620    /// ```
621    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
622    ///
623    /// let unsigned_3 = Field::unsigned(3);
624    ///
625    /// let scheme = Scheme::new([
626    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
627    /// ]);
628    ///
629    /// let bits = Bits::new([0xBA, 0x1C]);
630    /// let parts = scheme.split_bits_at(0, &bits);
631    ///
632    /// assert_eq!(bits_as::int8(&parts[0]), -6);
633    /// assert_eq!(bits_as::uint8(&parts[1]), 1);
634    /// assert_eq!(bits_as::uint8(&parts[2]), 2);
635    /// assert_eq!(bits_as::uint8(&parts[3]), 6);
636    /// assert_eq!(bits_as::uint8(&parts[4]), 1);
637    ///
638    /// let parts2 = scheme.split_bits_at(8, &bits);
639    ///
640    /// assert_eq!(bits_as::int8(&parts2[0]), -4);
641    /// assert_eq!(bits_as::uint8(&parts2[1]), 0);
642    /// assert_eq!(bits_as::uint8(&parts2[2]), 0);
643    /// assert_eq!(bits_as::uint8(&parts2[3]), 0);
644    /// assert_eq!(bits_as::uint8(&parts2[4]), 0);
645    ///
646    /// let scheme2 = Scheme::new([
647    ///     Field::aligned(23, -1, true),
648    ///     Field::aligned(0, -1, false),
649    ///     Field::bytes(-1, false),
650    ///     Field::signed(-1),
651    ///     Field::unsigned(-1),
652    ///     Field::unsigned(0),
653    ///     Field::unsigned(32),
654    ///     Field::bytes(4, false),
655    ///     Field::aligned(0, 8, false),
656    ///     Field::aligned(7, 8, true),
657    ///     Field::signed(-1),
658    ///     Field::unsigned(-1)
659    /// ]);
660    ///
661    /// let bytes = [0xBA, 0xDC, 0xFE, 0x10, 0x32];
662    /// let bits3 = Bits::from(bytes.as_slice()); // 38-bits
663    /// let parts = scheme2.split_bits_at(4, &bits3);
664    ///
665    /// assert_eq!(bits_as::int32(&parts[0]), 0x0FEDCB);
666    /// assert_eq!(parts[1], Bits::empty());
667    /// assert_eq!(bits_as::vec_u8(&parts[2]), vec![0x42]);
668    /// assert_eq!(bits_as::vec_i32(&parts[3]), vec![-2]);
669    /// assert_eq!(parts[4], Bits::empty());
670    /// assert_eq!(parts[5], Bits::empty());
671    /// assert_eq!(parts[6], Bits::zeros(32));
672    /// assert_eq!(parts[7], Bits::zeros(32));
673    /// assert_eq!(parts[8], Bits::empty());
674    /// assert_eq!(parts[9], Bits::zeros(56));
675    /// assert_eq!(parts[10], Bits::empty());
676    /// assert_eq!(parts[11], Bits::empty());
677    /// ```
678    pub fn split_bits_at(&self, index: usize, bits: &Bits) -> Vec<Bits> {
679        let length = bits.len();
680        let mut matches = Vec::with_capacity(self.0.len());
681        let mut index = index;
682
683        for field in &self.0 {
684            if index >= length {
685                matches.push(field.default());
686            } else {
687                let data = field.extract(&bits, length, index);
688                index += data.len();
689                matches.push(data);
690            }
691        }
692
693        matches
694    }
695
696    /// Extracts the data associated with the fields of this scheme
697    ///
698    /// # Example
699    /// ```
700    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
701    ///
702    /// let unsigned_3 = Field::unsigned(3);
703    ///
704    /// let scheme = Scheme::new([
705    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
706    /// ]);
707    ///
708    /// let parts = scheme.split_bytes([0xBA, 0x1C]);
709    ///
710    /// assert_eq!(bits_as::int8(&parts[0]), -6);
711    /// assert_eq!(bits_as::uint8(&parts[1]), 1);
712    /// assert_eq!(bits_as::uint8(&parts[2]), 2);
713    /// assert_eq!(bits_as::uint8(&parts[3]), 6);
714    /// assert_eq!(bits_as::uint8(&parts[4]), 1);
715    ///
716    /// let parts2 = scheme.split_bytes([0xBA]);
717    ///
718    /// assert_eq!(bits_as::int8(&parts2[0]), -6);
719    /// assert_eq!(bits_as::uint8(&parts2[1]), 1);
720    /// assert_eq!(bits_as::uint8(&parts2[2]), 2);
721    /// assert_eq!(bits_as::uint8(&parts2[3]), 0);
722    /// assert_eq!(bits_as::uint8(&parts2[4]), 0);
723    ///
724    /// let scheme2 = Scheme::new([
725    ///     Field::aligned(23, -1, true),
726    ///     Field::aligned(0, -1, false),
727    ///     Field::bytes(-1, false),
728    ///     Field::signed(-1),
729    ///     Field::unsigned(-1),
730    ///     Field::unsigned(0),
731    ///     Field::unsigned(32),
732    ///     Field::bytes(4, false),
733    ///     Field::aligned(0, 8, false),
734    ///     Field::aligned(7, 8, true),
735    ///     Field::signed(-1),
736    ///     Field::unsigned(-1)
737    /// ]);
738    ///
739    /// let parts = scheme2.split_bytes(vec![0xBA, 0xDC, 0xFE, 0x10, 0x32]);
740    ///
741    /// assert_eq!(bits_as::int32(&parts[0]), 0xFFFEDCBAu32 as i32);
742    /// assert_eq!(parts[1], Bits::empty());
743    /// assert_eq!(bits_as::vec_u8(&parts[2]), vec![0x21, 0x64]);
744    /// assert_eq!(parts[3], Bits::zeros(1));
745    /// assert_eq!(bits_as::int64(&parts[4]), 0);
746    /// assert_eq!(parts[5], Bits::empty());
747    /// assert_eq!(parts[6], Bits::zeros(32));
748    /// assert_eq!(parts[7], Bits::zeros(32));
749    /// assert_eq!(parts[8], Bits::empty());
750    /// assert_eq!(parts[9], Bits::zeros(56));
751    /// assert_eq!(parts[10], Bits::empty());
752    /// assert_eq!(parts[11], Bits::empty());
753    /// ```
754    pub fn split_bytes<I: IntoIterator<Item=u8>>(&self, bytes: I) -> Vec<Bits> {
755        self.split_bits_at(0, &Bits::new(bytes))
756    }
757
758    /// Extracts the data associated with the fields of this scheme.
759    ///
760    /// # Example
761    /// ```
762    /// # use bit_byte_bit::{bits_as, Bits, Field, Scheme};
763    ///
764    /// let unsigned_3 = Field::unsigned(3);
765    ///
766    /// let scheme = Scheme::new([
767    ///     Field::signed(5), Field::BIT, unsigned_3, unsigned_3, Field::UNSIGNED_4
768    /// ]);
769    ///
770    /// let parts = scheme.split_bytes_at(0, [0xBA, 0x1C]);
771    ///
772    /// assert_eq!(bits_as::int8(&parts[0]), -6);
773    /// assert_eq!(bits_as::uint8(&parts[1]), 1);
774    /// assert_eq!(bits_as::uint8(&parts[2]), 2);
775    /// assert_eq!(bits_as::uint8(&parts[3]), 6);
776    /// assert_eq!(bits_as::uint8(&parts[4]), 1);
777    ///
778    /// let parts2 = scheme.split_bytes_at(8, [0xBA, 0x1C]);
779    ///
780    /// assert_eq!(bits_as::int8(&parts2[0]), -4);
781    /// assert_eq!(bits_as::uint8(&parts2[1]), 0);
782    /// assert_eq!(bits_as::uint8(&parts2[2]), 0);
783    /// assert_eq!(bits_as::uint8(&parts2[3]), 0);
784    /// assert_eq!(bits_as::uint8(&parts2[4]), 0);
785    ///
786    /// let scheme2 = Scheme::new([
787    ///     Field::aligned(23, -1, true),
788    ///     Field::aligned(0, -1, false),
789    ///     Field::bytes(-1, false),
790    ///     Field::signed(-1),
791    ///     Field::unsigned(-1),
792    ///     Field::unsigned(0),
793    ///     Field::unsigned(32),
794    ///     Field::bytes(4, false),
795    ///     Field::aligned(0, 8, false),
796    ///     Field::aligned(7, 8, true),
797    ///     Field::signed(-1),
798    ///     Field::unsigned(-1)
799    /// ]);
800    ///
801    /// let parts = scheme2.split_bytes_at(4, [0xBA, 0xDC, 0xFE, 0x10, 0x32]);
802    ///
803    /// assert_eq!(bits_as::int32(&parts[0]), 0x0FEDCB);
804    /// assert_eq!(parts[1], Bits::empty());
805    /// assert_eq!(bits_as::vec_u8(&parts[2]), vec![0x42]);
806    /// assert_eq!(bits_as::vec_i32(&parts[3]), vec![6]);
807    /// assert_eq!(parts[4], Bits::empty());
808    /// assert_eq!(parts[5], Bits::empty());
809    /// assert_eq!(parts[6], Bits::zeros(32));
810    /// assert_eq!(parts[7], Bits::zeros(32));
811    /// assert_eq!(parts[8], Bits::empty());
812    /// assert_eq!(parts[9], Bits::zeros(56));
813    /// assert_eq!(parts[10], Bits::empty());
814    /// assert_eq!(parts[11], Bits::empty());
815    /// ```
816    pub fn split_bytes_at<I: IntoIterator<Item=u8>>(&self, index: usize, bytes: I) -> Vec<Bits> {
817        self.split_bits_at(index, &Bits::new(bytes))
818    }
819
820
821}
822