selinux/policy/
extensible_bitmap.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::error::ValidateError;
6use super::parser::PolicyCursor;
7use super::{
8    Array, Counted, PolicyValidationContext, Validate, ValidateArray, array_type,
9    array_type_validate_deref_both,
10};
11
12use std::cmp::Ordering;
13use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned, little_endian as le};
14
15/// Maximum number of [`MapItem`] objects in a single [`ExtensibleBitmap`].
16pub(super) const MAX_BITMAP_ITEMS: u32 = 0x40;
17
18/// Fixed expectation for number of bits per [`MapItem`] in every [`ExtensibleBitmap`].
19pub(super) const MAP_NODE_BITS: u32 = 8 * std::mem::size_of::<u64>() as u32;
20
21array_type!(ExtensibleBitmap, Metadata, Vec<MapItem>);
22
23array_type_validate_deref_both!(ExtensibleBitmap);
24
25impl ExtensibleBitmap {
26    /// Returns the number of bits described by this [`ExtensibleBitmap`].
27    pub fn num_elements(&self) -> u32 {
28        self.high_bit()
29    }
30
31    /// Returns whether the `index`'th bit in this bitmap is a 1-bit.
32    pub fn is_set(&self, index: u32) -> bool {
33        if index > self.high_bit() {
34            return false;
35        }
36
37        let map_items = &self.data;
38        if let Ok(i) = map_items.binary_search_by(|map_item| self.item_ordering(map_item, index)) {
39            let map_item = &map_items[i];
40            let item_index = index - map_item.start_bit.get();
41            return map_item.map.get() & (1 << item_index) != 0;
42        }
43
44        false
45    }
46
47    /// Returns an iterator that yields the indices of this [`ExtensibleBitmap`]'s set bits.
48    pub fn indices_of_set_bits<'a>(&'a self) -> impl Iterator<Item = u32> {
49        ExtensibleBitmapSpansIterator::<'a> { bitmap: self, map_item: 0, next_bit: 0 }
50            .flat_map(|span| span.low..=span.high)
51    }
52
53    /// Returns an iterator that returns a set of spans of continuous set bits.
54    /// Each span consists of inclusive low and high bit indexes (i.e. zero-based).
55    pub fn spans<'a>(&'a self) -> ExtensibleBitmapSpansIterator<'a> {
56        ExtensibleBitmapSpansIterator::<'a> { bitmap: self, map_item: 0, next_bit: 0 }
57    }
58
59    /// Returns the next bit after the bits in this [`ExtensibleBitmap`]. That is, the bits in this
60    /// [`ExtensibleBitmap`] may be indexed by the range `[0, Self::high_bit())`.
61    fn high_bit(&self) -> u32 {
62        self.metadata.high_bit.get()
63    }
64
65    fn item_ordering(&self, map_item: &MapItem, index: u32) -> Ordering {
66        let map_item_start_bit = map_item.start_bit.get();
67        if map_item_start_bit > index {
68            Ordering::Greater
69        } else if map_item_start_bit + self.metadata.map_item_size_bits.get() <= index {
70            Ordering::Less
71        } else {
72            Ordering::Equal
73        }
74    }
75}
76
77/// Describes the indexes of a span of "true" bits in an `ExtensibleBitmap`.
78/// Low and high values are inclusive, such that when `low==high`, the span consists
79/// of a single bit.
80#[derive(Debug, Clone, PartialEq)]
81pub(super) struct ExtensibleBitmapSpan {
82    pub low: u32,
83    pub high: u32,
84}
85
86/// Iterator returned by `ExtensibleBitmap::spans()`.
87pub(super) struct ExtensibleBitmapSpansIterator<'a> {
88    bitmap: &'a ExtensibleBitmap,
89    map_item: usize, // Zero-based `Vec<MapItem>` index.
90    next_bit: u32,   // Zero-based bit index within the bitmap.
91}
92
93impl ExtensibleBitmapSpansIterator<'_> {
94    /// Returns the zero-based index of the next bit with the specified value, if any.
95    fn next_bit_with_value(&mut self, is_set: bool) -> Option<u32> {
96        let map_item_size_bits = self.bitmap.metadata.map_item_size_bits.get();
97        let num_elements = self.bitmap.num_elements();
98
99        while self.next_bit < num_elements {
100            let (start_bit, map) = self
101                .bitmap
102                .data
103                .get(self.map_item)
104                .map_or((num_elements, 0), |item| (item.start_bit.get(), item.map.get()));
105
106            if start_bit > self.next_bit {
107                if is_set {
108                    // Skip the implicit "false" bits, to the next `MapItem`.
109                    self.next_bit = start_bit
110                } else {
111                    return Some(self.next_bit);
112                }
113            } else {
114                // Scan the `MapItem` for the next matching bit.
115                let next_map_item_bit = self.next_bit - start_bit;
116                for map_bit in next_map_item_bit..map_item_size_bits {
117                    if ((map & (1 << map_bit)) != 0) == is_set {
118                        self.next_bit = start_bit + map_bit;
119                        return Some(self.next_bit);
120                    }
121                }
122
123                // Move on to the next `MapItem`, which may not be contiguous with
124                // this one.
125                self.next_bit = start_bit + map_item_size_bits;
126                self.map_item += 1;
127            }
128        }
129
130        None
131    }
132}
133
134impl Iterator for ExtensibleBitmapSpansIterator<'_> {
135    type Item = ExtensibleBitmapSpan;
136
137    /// Returns the next span of at least one bit set in the bitmap.
138    fn next(&mut self) -> Option<Self::Item> {
139        let low = self.next_bit_with_value(true)?;
140        // End the span at the bit preceding either the next false bit, or the end of the bitmap.
141        let high =
142            self.next_bit_with_value(false).unwrap_or_else(|| self.bitmap.num_elements()) - 1;
143        Some(Self::Item { low, high })
144    }
145}
146
147impl Validate for Vec<ExtensibleBitmap> {
148    type Error = <ExtensibleBitmap as Validate>::Error;
149
150    fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
151        for extensible_bitmap in self {
152            extensible_bitmap.validate(context)?;
153        }
154
155        Ok(())
156    }
157}
158
159impl Validate for Metadata {
160    type Error = ValidateError;
161
162    /// Validates that [`ExtensibleBitmap`] metadata is internally consistent with data
163    /// representation assumptions.
164    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
165        // Only one size for `MapItem` instances is supported.
166        let found_size = self.map_item_size_bits.get();
167        if found_size != MAP_NODE_BITS {
168            return Err(ValidateError::InvalidExtensibleBitmapItemSize { found_size });
169        }
170
171        // High bit must be `MapItem` size-aligned.
172        let found_high_bit = self.high_bit.get();
173        if found_high_bit % found_size != 0 {
174            return Err(ValidateError::MisalignedExtensibleBitmapHighBit {
175                found_size,
176                found_high_bit,
177            });
178        }
179
180        // Count and high bit must be consistent.
181        let found_count = self.count.get();
182        if found_count * found_size > found_high_bit {
183            return Err(ValidateError::InvalidExtensibleBitmapHighBit {
184                found_size,
185                found_high_bit,
186                found_count,
187            });
188        }
189        if found_count > MAX_BITMAP_ITEMS {
190            return Err(ValidateError::InvalidExtensibleBitmapCount { found_count });
191        }
192        if found_high_bit != 0 && found_count == 0 {
193            return Err(ValidateError::ExtensibleBitmapNonZeroHighBitAndZeroCount);
194        }
195
196        Ok(())
197    }
198}
199
200#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
201#[repr(C, packed)]
202pub(super) struct Metadata {
203    /// How many bits on each `MapItem`.
204    map_item_size_bits: le::U32,
205    /// Highest bit, non-inclusive.
206    high_bit: le::U32,
207    /// The number of map items.
208    count: le::U32,
209}
210
211impl Counted for Metadata {
212    /// The number of [`MapItem`] objects that follow a [`Metadata`] is the value stored in the
213    /// `metadata.count` field.
214    fn count(&self) -> u32 {
215        self.count.get()
216    }
217}
218
219#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
220#[repr(C, packed)]
221pub(super) struct MapItem {
222    /// The first bit that this [`MapItem`] stores, relative to its [`ExtensibleBitmap`] range:
223    /// `[0, extensible_bitmap.high_bit())`.
224    start_bit: le::U32,
225    /// The bitmap data for this [`MapItem`].
226    map: le::U64,
227}
228
229impl Validate for [MapItem] {
230    type Error = anyhow::Error;
231
232    /// All [`MapItem`] validation requires access to [`Metadata`]; validation performed in
233    /// `ExtensibleBitmap<PS>::validate()`.
234    fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
235        Ok(())
236    }
237}
238
239impl ValidateArray<Metadata, MapItem> for ExtensibleBitmap {
240    type Error = anyhow::Error;
241
242    /// Validates that `metadata` and `data` are internally consistent. [`MapItem`] objects are
243    /// expected to be stored in ascending order (by `start_bit`), and their bit ranges must fall
244    /// within the range `[0, metadata.high_bit())`.
245    fn validate_array(
246        _context: &mut PolicyValidationContext,
247        metadata: &Metadata,
248        items: &[MapItem],
249    ) -> Result<(), Self::Error> {
250        let found_size = metadata.map_item_size_bits.get();
251        let found_high_bit = metadata.high_bit.get();
252
253        // `MapItem` objects must be in sorted order, each with a `MapItem` size-aligned starting bit.
254        //
255        // Note: If sorted order assumption is violated `ExtensibleBitmap::binary_search_items()` will
256        // misbehave and `ExtensibleBitmap` will need to be refactored accordingly.
257        let mut min_start: u32 = 0;
258        for map_item in items {
259            let found_start_bit = map_item.start_bit.get();
260            if found_start_bit % found_size != 0 {
261                return Err(ValidateError::MisalignedExtensibleBitmapItemStartBit {
262                    found_start_bit,
263                    found_size,
264                }
265                .into());
266            }
267            if found_start_bit < min_start {
268                return Err(ValidateError::OutOfOrderExtensibleBitmapItems {
269                    found_start_bit,
270                    min_start,
271                }
272                .into());
273            }
274            min_start = found_start_bit + found_size;
275        }
276
277        // Last `MapItem` object may not include bits beyond (and including) high bit value.
278        if min_start > found_high_bit {
279            return Err(ValidateError::ExtensibleBitmapItemOverflow {
280                found_items_end: min_start,
281                found_high_bit,
282            }
283            .into());
284        }
285
286        Ok(())
287    }
288}
289
290#[cfg(test)]
291mod tests {
292    use super::super::error::ParseError;
293    use super::super::parser::{PolicyCursor, PolicyData};
294    use super::super::testing::{as_parse_error, as_validate_error};
295    use super::super::{Parse, PolicyValidationContext};
296    use super::*;
297
298    use std::borrow::Borrow;
299    use std::sync::Arc;
300
301    macro_rules! parse_test {
302        ($parse_output:ident, $data:expr, $result:tt, $policy_data:tt, $check_impl:block) => {{
303            let data = Arc::new($data);
304            fn check_by_value(
305                $result: Result<($parse_output, PolicyCursor), <$parse_output as Parse>::Error>,
306                $policy_data: &PolicyData,
307            ) -> Option<($parse_output, PolicyCursor)> {
308                $check_impl
309            }
310
311            let by_value_result = $parse_output::parse(PolicyCursor::new(data.clone()));
312            let _ = check_by_value(by_value_result, &data);
313        }};
314    }
315
316    struct ExtensibleBitmapIterator<B: Borrow<ExtensibleBitmap>> {
317        extensible_bitmap: B,
318        i: u32,
319    }
320
321    impl<B: Borrow<ExtensibleBitmap>> Iterator for ExtensibleBitmapIterator<B> {
322        type Item = bool;
323
324        fn next(&mut self) -> Option<Self::Item> {
325            if self.i >= self.extensible_bitmap.borrow().high_bit() {
326                return None;
327            }
328            let value = self.extensible_bitmap.borrow().is_set(self.i);
329            self.i = self.i + 1;
330            Some(value)
331        }
332    }
333
334    impl ExtensibleBitmap {
335        fn iter(&self) -> ExtensibleBitmapIterator<&ExtensibleBitmap> {
336            ExtensibleBitmapIterator { extensible_bitmap: self, i: 0 }
337        }
338    }
339
340    #[test]
341    fn extensible_bitmap_simple() {
342        parse_test!(
343            ExtensibleBitmap,
344            [
345                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
346                MAP_NODE_BITS.to_le_bytes().as_slice(), // high bit for 1-item bitmap
347                (1 as u32).to_le_bytes().as_slice(), // count of `MapItem` entries in 1-item bitmap
348                (0 as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
349                (1 as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 0
350            ]
351            .concat(),
352            result,
353            _policy_data,
354            {
355                let (extensible_bitmap, tail) = result.expect("parse");
356                assert_eq!(24, tail.offset());
357                let mut count: u32 = 0;
358                for (i, bit) in extensible_bitmap.iter().enumerate() {
359                    assert!((i == 0 && bit) || (i > 0 && !bit));
360                    count = count + 1;
361                }
362                assert_eq!(MAP_NODE_BITS, count);
363                Some((extensible_bitmap, tail))
364            }
365        );
366    }
367
368    #[test]
369    fn extensible_bitmap_sparse_two_item() {
370        parse_test!(
371            ExtensibleBitmap,
372            [
373                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
374                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for 2-item bitmap
375                (2 as u32).to_le_bytes().as_slice(), // count of `MapItem` entries  in 2-item bitmap
376                ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
377                ((1 << 2) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 0
378                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
379                ((1 << 7) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 1
380            ]
381            .concat(),
382            result,
383            _policy_data,
384            {
385                let (extensible_bitmap, tail) = result.expect("parse");
386                assert_eq!(36, tail.offset());
387                for i in 0..(MAP_NODE_BITS * 10) {
388                    let expected = i == ((MAP_NODE_BITS * 2) + 2) || i == ((MAP_NODE_BITS * 7) + 7);
389                    assert_eq!(expected, extensible_bitmap.is_set(i));
390                }
391
392                let mut count: u32 = 0;
393                for (i, bit) in extensible_bitmap.iter().enumerate() {
394                    let expected = i == (((MAP_NODE_BITS * 2) + 2) as usize)
395                        || i == (((MAP_NODE_BITS * 7) + 7) as usize);
396                    assert_eq!(expected, bit);
397                    count = count + 1;
398                }
399                assert_eq!(MAP_NODE_BITS * 10, count);
400                Some((extensible_bitmap, tail))
401            }
402        );
403    }
404
405    #[test]
406    fn extensible_bitmap_sparse_malformed() {
407        parse_test!(
408            ExtensibleBitmap,
409            [
410                (MAP_NODE_BITS - 1).to_le_bytes().as_slice(), // invalid bits per node
411                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for 2-item bitmap
412                (2 as u32).to_le_bytes().as_slice(), // count of `MapItem` entries in 2-item bitmap
413                ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
414                ((1 << 2) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 0
415                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
416                ((1 << 7) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 1
417            ]
418            .concat(),
419            result,
420            policy_data,
421            {
422                let (parsed, tail) = result.expect("parsed");
423                assert_eq!(36, tail.offset());
424                let mut context = PolicyValidationContext { data: policy_data.clone() };
425                assert_eq!(
426                    Err(ValidateError::InvalidExtensibleBitmapItemSize {
427                        found_size: MAP_NODE_BITS - 1
428                    }),
429                    parsed.validate(&mut context).map_err(as_validate_error)
430                );
431                Some((parsed, tail))
432            }
433        );
434
435        parse_test!(
436            ExtensibleBitmap,
437            [
438                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
439                (((MAP_NODE_BITS * 10) + 1) as u32).to_le_bytes().as_slice(), // invalid high bit for 2-item bitmap
440                (2 as u32).to_le_bytes().as_slice(), // count of `MapItem` entries in 2-item bitmap
441                ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
442                ((1 << 2) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 0
443                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
444                ((1 << 7) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 1
445            ]
446            .concat(),
447            result,
448            policy_data,
449            {
450                let (parsed, tail) = result.expect("parsed");
451                assert_eq!(36, tail.offset());
452                let mut context = PolicyValidationContext { data: policy_data.clone() };
453                assert_eq!(
454                    Err(ValidateError::MisalignedExtensibleBitmapHighBit {
455                        found_size: MAP_NODE_BITS,
456                        found_high_bit: (MAP_NODE_BITS * 10) + 1
457                    }),
458                    parsed.validate(&mut context).map_err(as_validate_error),
459                );
460                Some((parsed, tail))
461            }
462        );
463
464        parse_test!(
465            ExtensibleBitmap,
466            [
467                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
468                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for 2-item bitmap
469                (11 as u32).to_le_bytes().as_slice(), // invalid count of `MapItem` entries in 2-item bitmap
470                ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
471                ((1 << 2) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 0
472                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
473                ((1 << 7) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 1
474            ]
475            .concat(),
476            result,
477            _policy_data,
478            {
479                match result.err().map(Into::<anyhow::Error>::into).map(as_parse_error) {
480                    // `PolicyCursor` attempts to read `Vec` one item at a time.
481                    Some(ParseError::MissingData { type_name, type_size, num_bytes: 0 }) => {
482                        assert_eq!(std::any::type_name::<MapItem>(), type_name);
483                        assert_eq!(std::mem::size_of::<MapItem>(), type_size);
484                    }
485                    v => {
486                        panic!(
487                            "Expected Some({:?}), but got {:?}",
488                            ParseError::MissingData {
489                                type_name: std::any::type_name::<MapItem>(),
490                                type_size: std::mem::size_of::<MapItem>(),
491                                num_bytes: 0,
492                            },
493                            v
494                        );
495                    }
496                };
497                None::<(ExtensibleBitmap, PolicyCursor)>
498            }
499        );
500
501        parse_test!(
502            ExtensibleBitmap,
503            [
504                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
505                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for 2-item bitmap
506                (2 as u32).to_le_bytes().as_slice(), // count of `MapItem` entries in 2-item bitmap
507                (((MAP_NODE_BITS * 2) + 1) as u32).to_le_bytes().as_slice(), // invalid start bit for `MapItem` 0
508                ((1 << 2) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 0
509                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
510                ((1 << 7) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 1
511            ]
512            .concat(),
513            result,
514            policy_data,
515            {
516                let (parsed, tail) = result.expect("parsed");
517                assert_eq!(36, tail.offset());
518                let mut context = PolicyValidationContext { data: policy_data.clone() };
519                match parsed.validate(&mut context).map_err(as_validate_error) {
520                    Err(ValidateError::MisalignedExtensibleBitmapItemStartBit {
521                        found_start_bit,
522                        ..
523                    }) => {
524                        assert_eq!((MAP_NODE_BITS * 2) + 1, found_start_bit);
525                    }
526                    parse_err => {
527                        assert!(
528                            false,
529                            "Expected Err(MisalignedExtensibleBitmapItemStartBit...), but got {:?}",
530                            parse_err
531                        );
532                    }
533                }
534                Some((parsed, tail))
535            }
536        );
537
538        parse_test!(
539            ExtensibleBitmap,
540            [
541                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
542                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for 2-item bitmap
543                (2 as u32).to_le_bytes().as_slice(), // count of `MapItem` entries in 2-item bitmap
544                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // out-of-order start bit for `MapItem` 0
545                ((1 << 7) as u64).to_le_bytes().as_slice(),            // bit values for `MapItem` 0
546                ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), // out-of-order start bit for `MapItem` 1
547                ((1 << 2) as u64).to_le_bytes().as_slice(),            // bit values for `MapItem` 1
548            ]
549            .concat(),
550            result,
551            policy_data,
552            {
553                let (parsed, tail) = result.expect("parsed");
554                assert_eq!(36, tail.offset());
555                let mut context = PolicyValidationContext { data: policy_data.clone() };
556                assert_eq!(
557                    parsed.validate(&mut context).map_err(as_validate_error),
558                    Err(ValidateError::OutOfOrderExtensibleBitmapItems {
559                        found_start_bit: MAP_NODE_BITS * 2,
560                        min_start: (MAP_NODE_BITS * 7) + MAP_NODE_BITS,
561                    })
562                );
563                Some((parsed, tail))
564            }
565        );
566
567        parse_test!(
568            ExtensibleBitmap,
569            [
570                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
571                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for 2-item bitmap
572                (3 as u32).to_le_bytes().as_slice(), // invalid count of `MapItem` entries in 2-item bitmap
573                ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
574                ((1 << 2) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 0
575                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
576                ((1 << 7) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 1
577            ]
578            .concat(),
579            result,
580            _policy_data,
581            {
582                match result.err().map(Into::<anyhow::Error>::into).map(as_parse_error) {
583                    // `PolicyCursor` attempts to read `Vec` one item at a time.
584                    Some(ParseError::MissingData { type_name, type_size, num_bytes: 0 }) => {
585                        assert_eq!(std::any::type_name::<MapItem>(), type_name);
586                        assert_eq!(std::mem::size_of::<MapItem>(), type_size);
587                    }
588                    parse_err => {
589                        assert!(
590                            false,
591                            "Expected Some({:?}), but got {:?}",
592                            ParseError::MissingData {
593                                type_name: std::any::type_name::<MapItem>(),
594                                type_size: std::mem::size_of::<MapItem>(),
595                                num_bytes: 0
596                            },
597                            parse_err
598                        );
599                    }
600                };
601                None::<(ExtensibleBitmap, PolicyCursor)>
602            }
603        );
604    }
605
606    #[test]
607    fn extensible_bitmap_spans_iterator() {
608        type Span = ExtensibleBitmapSpan;
609
610        // Single- and multi-bit spans.
611        parse_test!(
612            ExtensibleBitmap,
613            [
614                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
615                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for bitmap
616                (2 as u32).to_le_bytes().as_slice(),    // count of `MapItem` entries in bitmap
617                ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
618                ((1 << 2) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 0
619                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
620                ((1 << 7) | (1 << 8) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 1
621            ]
622            .concat(),
623            result,
624            _policy_data,
625            {
626                let (extensible_bitmap, tail) = result.expect("parse");
627                assert_eq!(36, tail.offset());
628
629                let mut iterator = extensible_bitmap.spans();
630                assert_eq!(
631                    iterator.next(),
632                    Some(Span { low: (MAP_NODE_BITS * 2) + 2, high: (MAP_NODE_BITS * 2) + 2 })
633                );
634                assert_eq!(
635                    iterator.next(),
636                    Some(Span { low: (MAP_NODE_BITS * 7) + 7, high: (MAP_NODE_BITS * 7) + 8 })
637                );
638                assert_eq!(iterator.next(), None);
639
640                Some((extensible_bitmap, tail))
641            }
642        );
643
644        // Multi-bit span that straddles two `MapItem`s.
645        parse_test!(
646            ExtensibleBitmap,
647            [
648                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
649                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for bitmap
650                (2 as u32).to_le_bytes().as_slice(),    // count of `MapItem` entries in bitmap
651                ((MAP_NODE_BITS * 6) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
652                ((1 as u64) << 63).to_le_bytes().as_slice(), // bit values for `MapItem` 0
653                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
654                ((1 << 0) | (1 << 1) as u64).to_le_bytes().as_slice(), // bit values for `MapItem` 1
655            ]
656            .concat(),
657            result,
658            _policy_data,
659            {
660                let (extensible_bitmap, tail) = result.expect("parse");
661                assert_eq!(36, tail.offset());
662
663                let mut iterator = extensible_bitmap.spans();
664                assert_eq!(
665                    iterator.next(),
666                    Some(Span { low: (MAP_NODE_BITS * 6) + 63, high: (MAP_NODE_BITS * 7) + 1 })
667                );
668                assert_eq!(iterator.next(), None);
669
670                Some((extensible_bitmap, tail))
671            }
672        );
673
674        // Multi-bit spans of full `MapItem`s, separated by an implicit span of false bits,
675        // and with further implicit spans of false bits at the end.
676        parse_test!(
677            ExtensibleBitmap,
678            [
679                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
680                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for bitmap
681                (2 as u32).to_le_bytes().as_slice(),    // count of `MapItem` entries in bitmap
682                ((MAP_NODE_BITS * 5) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
683                (u64::MAX).to_le_bytes().as_slice(),    // bit values for `MapItem` 0
684                ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 1
685                (u64::MAX).to_le_bytes().as_slice(),    // bit values for `MapItem` 1
686            ]
687            .concat(),
688            result,
689            _policy_data,
690            {
691                let (extensible_bitmap, tail) = result.expect("parse");
692                assert_eq!(36, tail.offset());
693
694                let mut iterator = extensible_bitmap.spans();
695                assert_eq!(
696                    iterator.next(),
697                    Some(Span { low: (MAP_NODE_BITS * 5), high: (MAP_NODE_BITS * 6) - 1 })
698                );
699                assert_eq!(
700                    iterator.next(),
701                    Some(Span { low: (MAP_NODE_BITS * 7), high: (MAP_NODE_BITS * 8) - 1 })
702                );
703                assert_eq!(iterator.next(), None);
704
705                Some((extensible_bitmap, tail))
706            }
707        );
708
709        // Span reaching the end of the bitmap is handled correctly.
710        parse_test!(
711            ExtensibleBitmap,
712            [
713                MAP_NODE_BITS.to_le_bytes().as_slice(), // bits per node
714                ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), // high bit for bitmap
715                (1 as u32).to_le_bytes().as_slice(),    // count of `MapItem` entries  in bitmap
716                ((MAP_NODE_BITS * 9) as u32).to_le_bytes().as_slice(), // start bit for `MapItem` 0
717                (u64::MAX).to_le_bytes().as_slice(),    // bit values for `MapItem` 0
718            ]
719            .concat(),
720            result,
721            _policy_data,
722            {
723                let (extensible_bitmap, tail) = result.expect("parse");
724                assert_eq!(24, tail.offset());
725
726                let mut iterator = extensible_bitmap.spans();
727                assert_eq!(
728                    iterator.next(),
729                    Some(Span { low: (MAP_NODE_BITS * 9), high: (MAP_NODE_BITS * 10) - 1 })
730                );
731                assert_eq!(iterator.next(), None);
732
733                Some((extensible_bitmap, tail))
734            }
735        );
736    }
737}