crabstep 0.5.0

Cross-platform, zero-dependency Apple/NeXTSTEP typedstream deserializer
Documentation
//! Helpers shared across the Foundation accessors.

use crate::deserializer::iter::{Property, PropertyIterator};

impl<'a, 'b: 'a> Property<'a, 'b> {
    /// If `self` is a group whose first item is an object whose class is in
    /// `classes`, return that object's data iterator.
    pub(crate) fn object_in_classes(&self, classes: &[&str]) -> Option<PropertyIterator<'a, 'b>> {
        match self {
            // `self` is the object directly (e.g. from `root()`/`resolve_object`).
            Property::Object { name, data, .. } if classes.contains(name) => Some(data.clone()),
            // `self` is a group whose first item is the object (iteration).
            Property::Group(group) => match group.first()? {
                Property::Object { name, data, .. } if classes.contains(&name) => Some(data),
                _ => None,
            },
            _ => None,
        }
    }
}

/// Read the leading count group of a container's data, returning the remaining
/// iterator (positioned at the first element/entry) and the declared count.
pub(crate) fn split_count<'a, 'b: 'a>(
    mut data: PropertyIterator<'a, 'b>,
) -> Option<(PropertyIterator<'a, 'b>, usize)> {
    let count = data.next()?;
    // A non-integer or negative count means this isn't a well-formed container;
    // signal that rather than reporting a bogus zero length.
    let len = usize::try_from(count.as_i64()?).ok()?;
    Some((data, len))
}