geometric-traits 0.2.2

Trait-based algebraic and graph algorithms for Rust, supporting no_std environments
Documentation
use core::{iter::Cloned, ops::Range};

use crate::{prelude::*, traits::Symbol};

impl<V: Symbol> Vocabulary for [V] {
    type SourceSymbol = usize;
    type DestinationSymbol = V;
    type Sources<'a>
        = Range<usize>
    where
        Self: 'a;
    type Destinations<'a>
        = Cloned<core::slice::Iter<'a, Self::DestinationSymbol>>
    where
        Self: 'a;

    #[inline]
    fn convert(&self, source: &Self::SourceSymbol) -> Option<Self::DestinationSymbol> {
        self.get(*source).cloned()
    }

    #[inline]
    fn len(&self) -> usize {
        self.len()
    }

    #[inline]
    fn sources(&self) -> Self::Sources<'_> {
        0..self.len()
    }

    #[inline]
    fn destinations(&self) -> Self::Destinations<'_> {
        self.iter().cloned()
    }
}

impl<V: Symbol> VocabularyRef for [V] {
    type DestinationRefs<'a>
        = core::slice::Iter<'a, Self::DestinationSymbol>
    where
        Self: 'a;

    #[inline]
    fn convert_ref(&self, source: &Self::SourceSymbol) -> Option<&Self::DestinationSymbol> {
        self.get(*source)
    }

    #[inline]
    fn destination_refs(&self) -> Self::DestinationRefs<'_> {
        self.iter()
    }
}

impl<V: Symbol> BidirectionalVocabulary for [V] {
    #[inline]
    fn invert(&self, destination: &Self::DestinationSymbol) -> Option<Self::SourceSymbol> {
        self.iter().position(|v| v == destination)
    }
}

#[cfg(all(test, feature = "alloc"))]
mod tests {
    use alloc::vec::Vec;

    use crate::traits::{BidirectionalVocabulary, Vocabulary, VocabularyRef};

    #[test]
    fn test_slice_vocabulary_len() {
        let data = [10, 20, 30];
        let slice: &[i32] = &data;
        assert_eq!(Vocabulary::len(slice), 3);
    }

    #[test]
    fn test_slice_vocabulary_convert() {
        let data = ["a", "b", "c"];
        let slice: &[&str] = &data;
        assert_eq!(slice.convert(&0), Some("a"));
        assert_eq!(slice.convert(&1), Some("b"));
        assert_eq!(slice.convert(&2), Some("c"));
        assert_eq!(slice.convert(&3), None);
    }

    #[test]
    fn test_slice_vocabulary_sources() {
        let data = [1, 2, 3];
        let slice: &[i32] = &data;
        let sources: Vec<usize> = slice.sources().collect();
        assert_eq!(sources, vec![0, 1, 2]);
    }

    #[test]
    fn test_slice_vocabulary_destinations() {
        let data = [10, 20, 30];
        let slice: &[i32] = &data;
        let destinations: Vec<i32> = slice.destinations().collect();
        assert_eq!(destinations, vec![10, 20, 30]);
    }

    #[test]
    fn test_slice_vocabulary_ref_convert_ref() {
        let data = [100, 200];
        let slice: &[i32] = &data;
        assert_eq!(slice.convert_ref(&0), Some(&100));
        assert_eq!(slice.convert_ref(&1), Some(&200));
        assert_eq!(slice.convert_ref(&2), None);
    }

    #[test]
    fn test_slice_vocabulary_ref_destination_refs() {
        let data = [1, 2];
        let slice: &[i32] = &data;
        let refs: Vec<&i32> = slice.destination_refs().collect();
        assert_eq!(refs, vec![&1, &2]);
    }

    #[test]
    fn test_slice_bidirectional_vocabulary_invert() {
        let data = ["x", "y", "z"];
        let slice: &[&str] = &data;
        assert_eq!(slice.invert(&"x"), Some(0));
        assert_eq!(slice.invert(&"y"), Some(1));
        assert_eq!(slice.invert(&"z"), Some(2));
        assert_eq!(slice.invert(&"w"), None);
    }

    #[test]
    fn test_slice_empty() {
        let data: [i32; 0] = [];
        let slice: &[i32] = &data;
        assert_eq!(Vocabulary::len(slice), 0);
        assert_eq!(slice, []);
    }
}