summaryrefslogtreecommitdiffstats
path: root/vendor/gix-config/src/file/impls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix-config/src/file/impls.rs')
-rw-r--r--vendor/gix-config/src/file/impls.rs111
1 files changed, 111 insertions, 0 deletions
diff --git a/vendor/gix-config/src/file/impls.rs b/vendor/gix-config/src/file/impls.rs
new file mode 100644
index 000000000..c26df5fb8
--- /dev/null
+++ b/vendor/gix-config/src/file/impls.rs
@@ -0,0 +1,111 @@
+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
+ }
+}