patch-xml 0.0.3

Load and patch xml files. Pre-alpha version. No stable interface until version 0.1.0.
use std::str::FromStr;

#[derive(Debug, Clone)]
pub enum CaptureReference {
    Number(usize),
    Name(String),
    WholeExpression,
}

#[derive(Debug, Clone)]
pub struct SegmentReference {
    pub path: String,
    pub capture: CaptureReference,
}

#[derive(Debug, Clone)]
pub enum Segment {
    String(String),
    Reference(SegmentReference),
}

impl From<String> for SegmentReference {
    fn from(segment_reference_string: String) -> Self {
        let parts: Vec<&str> = segment_reference_string.split(":").collect();
        if parts.len() == 0 {
            panic!("Empty references are not allowed");
        } else if parts.len() == 1 {
            SegmentReference {
                path: parts.get(0).unwrap().to_string(),
                capture: CaptureReference::WholeExpression,
            }
        } else if parts.len() == 2 {
            let capture_reference = parts.get(1).unwrap().to_string();
            match usize::from_str(&capture_reference) {
                Ok(index) => SegmentReference {
                    path: parts.get(0).unwrap().to_string(),
                    capture: CaptureReference::Number(index),
                },
                Err(_) => SegmentReference {
                    path: parts.get(0).unwrap().to_string(),
                    capture: CaptureReference::Name(capture_reference),
                },
            }
        } else {
            panic!("A reference must have a path and optionally a capture-reference. Not more.");
        }
    }
}

impl From<&str> for SegmentReference {
    fn from(segment_reference_string: &str) -> Self {
        SegmentReference::from(segment_reference_string.to_string())
    }
}

impl Segment {
    pub fn to_string(&self) -> String {
        match self {
            Segment::String(segment) => segment.clone(),
            Segment::Reference(reference) => format!("[{}]", reference.to_string()),
        }
    }
}

impl PartialEq for Segment {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Segment::String(s1), Segment::String(s2)) => s1 == s2,
            (Segment::Reference(s1), Segment::Reference(s2)) => s1 == s2,
            _ => false,
        }
    }
}

impl SegmentReference {
    pub fn to_string(&self) -> String {
        match &self.capture {
            CaptureReference::Number(n) => format!("{}:{}", self.path, n).to_string(),
            CaptureReference::Name(n) => format!("{}:{}", self.path, n).to_string(),
            CaptureReference::WholeExpression => format!("{}", self.path).to_string(),
        }
    }
}

impl PartialEq for SegmentReference {
    fn eq(&self, other: &Self) -> bool {
        self.path == other.path
            && match (&self.capture, &other.capture) {
                (CaptureReference::WholeExpression, CaptureReference::WholeExpression) => true,
                (CaptureReference::Name(n1), CaptureReference::Name(n2)) => n1 == n2,
                (CaptureReference::Number(n1), CaptureReference::Number(n2)) => n1 == n2,
                (_, _) => false,
            }
    }
}