Sebastian Thielmake fmt47724c04 years agoHistory
111 lines · 3.6 KB · Rust
RawDownload
use std::{borrow::Cow, convert::TryFrom, fmt::Display, str::FromStr}; use bstr::{BStr, BString, ByteVec}; use crate::{    file::Metadata,    parse,    parse::{section, Event},    value::normalize,    File,}; impl FromStr for File<'static> {    type Err = parse::Error;     fn from_str(s: &str) -> Result<Self, Self::Err> {        parse::Events::from_bytes_owned(s.as_bytes(), None)            .map(|events| File::from_parse_events_no_includes(events, Metadata::api()))    }} impl<'a> TryFrom<&'a str> for File<'a> {    type Error = parse::Error;     /// Convenience constructor. Attempts to parse the provided string into a    /// [`File`]. See [`Events::from_str()`][crate::parse::Events::from_str()] for more information.    fn try_from(s: &'a str) -> Result<File<'a>, Self::Error> {        parse::Events::from_str(s).map(|events| Self::from_parse_events_no_includes(events, Metadata::api()))    }} impl<'a> TryFrom<&'a BStr> for File<'a> {    type Error = parse::Error;     /// Convenience constructor. Attempts to parse the provided byte string into    /// a [`File`]. See [`Events::from_bytes()`][parse::Events::from_bytes()] for more information.    fn try_from(value: &'a BStr) -> Result<File<'a>, Self::Error> {        parse::Events::from_bytes(value, None)            .map(|events| Self::from_parse_events_no_includes(events, Metadata::api()))    }} impl From<File<'_>> for BString {    fn from(c: File<'_>) -> Self {        c.into()    }} impl Display for File<'_> {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        Display::fmt(&self.to_bstring(), f)    }} impl PartialEq for File<'_> {    fn eq(&self, other: &Self) -> bool {        fn find_key<'a>(mut it: impl Iterator<Item = &'a Event<'a>>) -> Option<&'a section::Key<'a>> {            it.find_map(|e| match e {                Event::SectionKey(k) => Some(k),                _ => None,            })        }        fn collect_value<'a>(it: impl Iterator<Item = &'a Event<'a>>) -> Cow<'a, BStr> {            let mut partial_value = BString::default();            let mut value = None;             for event in it {                match event {                    Event::SectionKey(_) => break,                    Event::Value(v) => {                        value = v.clone().into();                        break;                    }                    Event::ValueNotDone(v) => partial_value.push_str(v.as_ref()),                    Event::ValueDone(v) => {                        partial_value.push_str(v.as_ref());                        value = Some(partial_value.into());                        break;                    }                    _ => (),                }            }            value.map(normalize).unwrap_or_default()        }        if self.section_order.len() != other.section_order.len() {            return false;        }         for (lhs, rhs) in self            .section_order            .iter()            .zip(&other.section_order)            .map(|(lhs, rhs)| (&self.sections[lhs], &other.sections[rhs]))        {            if !(lhs.header.name == rhs.header.name && lhs.header.subsection_name == rhs.header.subsection_name) {                return false;            }             let (mut lhs, mut rhs) = (lhs.body.0.iter(), rhs.body.0.iter());            while let (Some(lhs_key), Some(rhs_key)) = (find_key(&mut lhs), find_key(&mut rhs)) {                if lhs_key != rhs_key {                    return false;                }                if collect_value(&mut lhs) != collect_value(&mut rhs) {                    return false;                }            }        }        true    }}