yamlette 0.1.1

Complete and comprehensive YAML 1.2 processor, written in pure rust
Documentation
use crate::book::extractor::traits::FromPointer;
use crate::book::volume::Volume;
use crate::book::word::Word;

#[derive(Copy, Clone)]
pub struct Pointer<'a> {
    vol: &'a Volume,
    pos: usize,
}

impl<'a, T> PartialEq<T> for Pointer<'a>
where
    T: PartialEq + FromPointer<'a>,
{
    fn eq(&self, other: &T) -> bool {
        if let Some(v) = <T as FromPointer>::from_pointer(*self) {
            *other == v
        } else {
            false
        }
    }
}

impl<'a> Pointer<'a> {
    pub fn new(vol: &'a Volume) -> Option<Self> {
        if vol.gist.len() > 0 {
            Some(Pointer { vol: vol, pos: 0 })
        } else {
            None
        }
    }

    pub fn into<T>(self) -> Option<T>
    where
        &'a Word: Into<Result<T, &'a Word>>,
    {
        let result: Result<T, _> = self.unalias().to_word().into();
        result.ok()
    }

    pub fn unalias(self) -> Pointer<'a> {
        match self.vol.gist[self.pos] {
            (_, _, Word::Alias(sz)) => Pointer::unalias(Pointer {
                vol: self.vol,
                pos: sz,
            }),
            _ => self,
        }
    }

    pub fn to_word(self) -> &'a Word {
        let (_, _, ref word) = self.vol.gist[self.pos];
        word
    }

    pub fn next_sibling(self) -> Option<Pointer<'a>> {
        let (_, level, _) = self.vol.gist[self.pos];

        for i in (self.pos + 1)..self.vol.gist.len() {
            let (_, sub, _) = self.vol.gist[i];
            if sub == level {
                return Some(Pointer {
                    vol: self.vol,
                    pos: i,
                });
            }
            if sub < level {
                break;
            };
        }

        None
    }

    pub fn count_siblings(self) -> usize {
        let (_, level, _) = self.vol.gist[self.pos];

        let mut cnt = 1;
        for i in (self.pos + 1)..self.vol.gist.len() {
            let (_, sub, _) = self.vol.gist[i];
            if sub == level {
                cnt += 1;
            }
            if sub < level {
                break;
            };
        }

        cnt
    }

    pub fn into_seq(self) -> Option<Pointer<'a>> {
        let ptr = self.unalias();

        let (_, level, ref word) = self.vol.gist[ptr.pos];

        match *word {
            Word::Seq(_) => {
                if let Some(&(_, sublevel, _)) = self.vol.gist.get(ptr.pos + 1) {
                    if sublevel == level + 1 {
                        Some(Pointer {
                            vol: ptr.vol,
                            pos: ptr.pos + 1,
                        })
                    } else {
                        None
                    }
                } else {
                    None
                }
            }
            _ => None,
        }
    }

    pub fn into_map(self) -> Option<Pointer<'a>> {
        let ptr = self.unalias();

        let (_, level, ref word) = self.vol.gist[ptr.pos];

        match *word {
            Word::Map(_) => {
                if let Some(&(_, sublevel, _)) = self.vol.gist.get(ptr.pos + 1) {
                    if sublevel == level + 1 {
                        Some(Pointer {
                            vol: ptr.vol,
                            pos: ptr.pos + 1,
                        })
                    } else {
                        None
                    }
                } else {
                    None
                }
            }
            _ => None,
        }
    }
}