217 lines · 5.4 KB · Rust
RawDownload
#![forbid(unsafe_code)]// #![forbid(rust_2018_idioms)]#![allow(dead_code)] use std::ops::Range; #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]struct Span {    pub start: usize,    pub end_inclusive: usize,} impl From<Span> for Range<usize> {    fn from(Span { start, end_inclusive }: Span) -> Self {        Range {            start,            end: end_inclusive + 1,        }    }} impl Span {    fn to_range(&self) -> Range<usize> {        self.clone().into()    }} pub mod file;pub use file::File; mod value {    pub enum Color {        Red,        BrightRed,        Ansi { r: u8, g: u8, c: u8 },    }     mod resolve {        use bstr::BStr;        use quick_error::quick_error;        use std::path::PathBuf;         quick_error! {            #[derive(Debug)]            pub enum Error {                Tbd {                    display("TBD")                }            }        }        pub fn path(_value: &BStr) -> Result<PathBuf, Error> {            unimplemented!("path_resolve")        }    }} mod spanned {    use crate::Span;    // we parse leading and trailing whitespace into comments, avoiding the notion of whitespace.    // This means we auto-trim whitespace otherwise, which I consider a feature    pub(crate) type Comment = Span;     pub(crate) struct Section {        pub(crate) name: Span,        pub(crate) sub_name: Option<Span>,    }     pub(crate) struct Entry {        pub(crate) name: Span,        pub(crate) value: Option<Span>,    }} mod owned {    use crate::Span;    use bstr::BString;     pub struct Entry {        pub name: BString,        pub value: Option<BString>,        pub(crate) span: Option<Span>,    }     pub struct Section {        pub name: BString,        pub sub_name: Option<BString>,        pub entries: Vec<Entry>,        pub(crate) span: Option<Span>,    }     impl Entry {        pub fn new(name: BString, value: Option<BString>) -> Self {            Entry {                name,                value,                span: None,            }        }         pub fn name(mut self, name: impl Into<BString>) -> Self {            self.name = name.into();            self        }        pub fn value(mut self, name: Option<BString>) -> Self {            self.value = name;            self        }    }     impl Section {        pub fn new(name: BString, sub_name: Option<BString>, entries: Vec<Entry>) -> Self {            Section {                name,                sub_name,                entries,                span: None,            }        }         pub fn name(mut self, name: impl Into<BString>) -> Self {            self.name = name.into();            self        }        pub fn sub_name(mut self, sub_name: Option<BString>) -> Self {            self.sub_name = sub_name;            self        }    }} mod borrowed {    use crate::{file::File, owned};     pub struct Entry<'a> {        pub(crate) parent: &'a File,        pub(crate) index: usize,    }     impl<'a> Entry<'a> {        pub fn to_editable(&self) -> owned::Entry {            let entry = self.parent.token(self.index).as_entry().expect("entry");            owned::Entry {                name: self.parent.bytes_at(entry.name).into(),                value: entry.value.map(|span| self.parent.bytes_at(span).into()),                span: Some(entry.name),            }        }    }     pub struct Section<'a> {        pub(crate) parent: &'a File,        pub(crate) index: usize,    }     impl<'a> Section<'a> {        pub fn to_editable(&self) -> owned::Section {            let section = self.parent.token(self.index).as_section().expect("section");            owned::Section {                name: self.parent.bytes_at(section.name).into(),                sub_name: section.sub_name.map(|span| self.parent.bytes_at(span).into()),                span: Some(section.name),                entries: self.entries().map(|e| e.to_editable()).collect(),            }        }    }} mod decode {    use crate::{borrowed, value};    use bstr::BStr;    use quick_error::quick_error;    use std::{borrow::Cow, path::PathBuf};     quick_error! {        #[derive(Debug)]        pub enum Error {            Tbd {                display("let's see what can go wrong and how we do it")            }            NoValue {                display("Entry has no value (TODO: much more error information)")            }        }    }     pub fn value(_input: &BStr) -> Result<Cow<'_, BStr>, Error> {        unimplemented!("decode value from bstr")    }     impl<'a> borrowed::Entry<'a> {        pub fn as_string(&self) -> Result<Cow<'a, BStr>, Error> {            value(                self.parent.bytes_at(                    self.parent                        .token(self.index)                        .as_entry()                        .expect("entry")                        .value                        .ok_or_else(|| Error::NoValue)?,                ),            )            .map_err(Into::into)        }        pub fn as_int(&self) -> Result<i64, Error> {            unimplemented!("as int")        }        pub fn as_bool(&self) -> Result<bool, Error> {            unimplemented!("as bool")        }        pub fn as_path(&self) -> Result<PathBuf, Error> {            unimplemented!("as bool")        }        pub fn as_color(&self) -> Result<value::Color, Error> {            unimplemented!("as bool")        }    }}