treeclocks 0.6.3

Various Tree Clock data-structures and utilities
Documentation
use super::*;
use thiserror::Error;

#[derive(Debug, PartialEq, Eq, Error)]
pub enum IdTreeParseError {
    #[error("Invalid value encountered {0}")]
    InvalidValue(u32),

    #[error("Unable to find the split")]
    NoSplit,

    #[error("Unknown characters")]
    Unknown,
}

impl std::str::FromStr for IdTree {
    type Err = IdTreeParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let s = s.trim();
        if let Ok(val) = s.parse::<u32>() {
            match val {
                0 => Ok(IdTree::Zero),
                1 => Ok(IdTree::One),
                val => Err(IdTreeParseError::InvalidValue(val)),
            }
        } else if s.starts_with('(') && s.ends_with(')') {
            let s = &s[1..s.len() - 1];

            let (left, right) = if s.starts_with('(') {
                let mut acc = 0;
                let (idx, _) = s
                    .char_indices()
                    .take_while(|(_idx, c)| {
                        match c {
                            '(' => acc += 1,
                            ')' => acc -= 1,
                            _ => {}
                        }

                        acc != 0
                    })
                    .last()
                    .ok_or(IdTreeParseError::NoSplit)?;

                let (left, right) = s.split_at(idx + 2);
                let right = &right[1..];
                (left, right)
            } else {
                s.split_once(',').ok_or(IdTreeParseError::NoSplit)?
            };

            let left = left.parse::<Self>()?;
            let right = right.parse::<Self>()?;
            Ok(IdTree::subtree(left, right))
        } else {
            Err(IdTreeParseError::Unknown)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse() {
        let strs = [
            "(0, 1)",
            "((1, 0), 1)",
            "(((1, 0), (0, (1, 0))), (((1, 0), (0, 1)), (1, 0)))",
        ];

        for s in strs {
            let id: IdTree = s.parse().expect(&format!("Unable to parse {s}"));
            assert_eq!(format!("{id}"), s);
        }
    }
}