use crate::file::SectionBody;use crate::parser::{parse_from_bytes, parse_from_str, Error, Event, Parser};use crate::File;use std::convert::TryFrom;use std::fmt::Display;impl<'a> TryFrom<&'a str> for File<'a> { type Error = Error<'a>; /// Convenience constructor. Attempts to parse the provided string into a /// [`File`]. See [`parse_from_str`] for more information. /// /// [`parse_from_str`]: crate::parser::parse_from_str fn try_from(s: &'a str) -> Result<File<'a>, Self::Error> { parse_from_str(s).map(Self::from) }}impl<'a> TryFrom<&'a [u8]> for File<'a> { type Error = Error<'a>; /// Convenience constructor. Attempts to parse the provided byte string into //// a [`File`]. See [`parse_from_bytes`] for more information. /// /// [`parse_from_bytes`]: crate::parser::parse_from_bytes fn try_from(value: &'a [u8]) -> Result<File<'a>, Self::Error> { parse_from_bytes(value).map(File::from) }}impl<'a> TryFrom<&'a Vec<u8>> for File<'a> { type Error = Error<'a>; /// Convenience constructor. Attempts to parse the provided byte string into //// a [`File`]. See [`parse_from_bytes`] for more information. /// /// [`parse_from_bytes`]: crate::parser::parse_from_bytes fn try_from(value: &'a Vec<u8>) -> Result<File<'a>, Self::Error> { parse_from_bytes(value).map(File::from) }}impl<'a> From<Parser<'a>> for File<'a> { fn from(parser: Parser<'a>) -> Self { let mut new_self = Self::default(); // Current section that we're building let mut prev_section_header = None; let mut section_events = SectionBody::new(); #[allow(clippy::explicit_into_iter_loop)] // it's not really an iterator (yet), needs streaming iterator support for event in parser.into_iter() { match event { Event::SectionHeader(header) => { if let Some(prev_header) = prev_section_header.take() { new_self.push_section_internal(prev_header, section_events); } else { new_self.frontmatter_events = section_events; } prev_section_header = Some(header); section_events = SectionBody::new(); } e @ Event::Key(_) | e @ Event::Value(_) | e @ Event::ValueNotDone(_) | e @ Event::ValueDone(_) | e @ Event::KeyValueSeparator => section_events.as_mut().push(e), e @ Event::Comment(_) | e @ Event::Newline(_) | e @ Event::Whitespace(_) => { section_events.as_mut().push(e); } } } // The last section doesn't get pushed since we only push if there's a // new section header, so we need to call push one more time. if let Some(header) = prev_section_header { new_self.push_section_internal(header, section_events); } else { new_self.frontmatter_events = section_events; } new_self }}impl From<File<'_>> for Vec<u8> { fn from(c: File<'_>) -> Self { c.into() }}impl From<&File<'_>> for Vec<u8> { fn from(config: &File<'_>) -> Self { let mut value = Self::new(); for events in config.frontmatter_events.as_ref() { value.extend(events.to_vec()); } for section_id in &config.section_order { value.extend( config .section_headers .get(section_id) .expect("section_header does not contain section id from section_order") .to_vec(), ); for event in config .sections .get(section_id) .expect("sections does not contain section id from section_order") .as_ref() { value.extend(event.to_vec()); } } value }}impl Display for File<'_> { /// Note that this is a best-effort attempt at printing a `GitConfig`. If /// there are non UTF-8 values in your config, this will _NOT_ render as /// read. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for front_matter in self.frontmatter_events.as_ref() { front_matter.fmt(f)?; } for section_id in &self.section_order { self.section_headers.get(section_id).unwrap().fmt(f)?; for event in self.sections.get(section_id).unwrap().as_ref() { event.fmt(f)?; } } Ok(()) }}
use crate::file::SectionBody;
use crate::parser::{parse_from_bytes, parse_from_str, Error, Event, Parser};
use crate::File;
use std::convert::TryFrom;
use std::fmt::Display;
impl<'a> TryFrom<&'a str> for File<'a> {
type Error = Error<'a>;
/// Convenience constructor. Attempts to parse the provided string into a
/// [`File`]. See [`parse_from_str`] for more information.
///
/// [`parse_from_str`]: crate::parser::parse_from_str
fn try_from(s: &'a str) -> Result<File<'a>, Self::Error> {
parse_from_str(s).map(Self::from)
}
}
impl<'a> TryFrom<&'a [u8]> for File<'a> {
type Error = Error<'a>;
/// Convenience constructor. Attempts to parse the provided byte string into
//// a [`File`]. See [`parse_from_bytes`] for more information.
///
/// [`parse_from_bytes`]: crate::parser::parse_from_bytes
fn try_from(value: &'a [u8]) -> Result<File<'a>, Self::Error> {
parse_from_bytes(value).map(File::from)
}
}
impl<'a> TryFrom<&'a Vec<u8>> for File<'a> {
type Error = Error<'a>;
/// Convenience constructor. Attempts to parse the provided byte string into
//// a [`File`]. See [`parse_from_bytes`] for more information.
///
/// [`parse_from_bytes`]: crate::parser::parse_from_bytes
fn try_from(value: &'a Vec<u8>) -> Result<File<'a>, Self::Error> {
parse_from_bytes(value).map(File::from)
}
}
impl<'a> From<Parser<'a>> for File<'a> {
fn from(parser: Parser<'a>) -> Self {
let mut new_self = Self::default();
// Current section that we're building
let mut prev_section_header = None;
let mut section_events = SectionBody::new();
#[allow(clippy::explicit_into_iter_loop)]
// it's not really an iterator (yet), needs streaming iterator support
for event in parser.into_iter() {
match event {
Event::SectionHeader(header) => {
if let Some(prev_header) = prev_section_header.take() {
new_self.push_section_internal(prev_header, section_events);
} else {
new_self.frontmatter_events = section_events;
}
prev_section_header = Some(header);
section_events = SectionBody::new();
}
e @ Event::Key(_)
| e @ Event::Value(_)
| e @ Event::ValueNotDone(_)
| e @ Event::ValueDone(_)
| e @ Event::KeyValueSeparator => section_events.as_mut().push(e),
e @ Event::Comment(_) | e @ Event::Newline(_) | e @ Event::Whitespace(_) => {
section_events.as_mut().push(e);
}
}
}
// The last section doesn't get pushed since we only push if there's a
// new section header, so we need to call push one more time.
if let Some(header) = prev_section_header {
new_self.push_section_internal(header, section_events);
} else {
new_self.frontmatter_events = section_events;
}
new_self
}
}
impl From<File<'_>> for Vec<u8> {
fn from(c: File<'_>) -> Self {
c.into()
}
}
impl From<&File<'_>> for Vec<u8> {
fn from(config: &File<'_>) -> Self {
let mut value = Self::new();
for events in config.frontmatter_events.as_ref() {
value.extend(events.to_vec());
}
for section_id in &config.section_order {
value.extend(
config
.section_headers
.get(section_id)
.expect("section_header does not contain section id from section_order")
.to_vec(),
);
for event in config
.sections
.get(section_id)
.expect("sections does not contain section id from section_order")
.as_ref()
{
value.extend(event.to_vec());
}
}
value
}
}
impl Display for File<'_> {
/// Note that this is a best-effort attempt at printing a `GitConfig`. If
/// there are non UTF-8 values in your config, this will _NOT_ render as
/// read.
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for front_matter in self.frontmatter_events.as_ref() {
front_matter.fmt(f)?;
}
for section_id in &self.section_order {
self.section_headers.get(section_id).unwrap().fmt(f)?;
for event in self.sections.get(section_id).unwrap().as_ref() {
event.fmt(f)?;
}
}
Ok(())
}
}