diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/gix-config/src/file/section/mod.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-config/src/file/section/mod.rs')
-rw-r--r-- | vendor/gix-config/src/file/section/mod.rs | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/vendor/gix-config/src/file/section/mod.rs b/vendor/gix-config/src/file/section/mod.rs new file mode 100644 index 000000000..e8e331084 --- /dev/null +++ b/vendor/gix-config/src/file/section/mod.rs @@ -0,0 +1,145 @@ +use std::{borrow::Cow, ops::Deref}; + +use bstr::{BStr, BString, ByteSlice}; +use smallvec::SmallVec; + +use crate::{ + file, + file::{Metadata, Section, SectionMut}, + parse, + parse::{section, Event}, +}; + +pub(crate) mod body; +pub use body::{Body, BodyIter}; +use gix_features::threading::OwnShared; + +use crate::file::{ + write::{extract_newline, platform_newline}, + SectionId, +}; + +impl<'a> Deref for Section<'a> { + type Target = Body<'a>; + + fn deref(&self) -> &Self::Target { + &self.body + } +} + +/// Instantiation and conversion +impl<'a> Section<'a> { + /// Create a new section with the given `name` and optional, `subsection`, `meta`-data and an empty body. + pub fn new( + name: impl Into<Cow<'a, str>>, + subsection: impl Into<Option<Cow<'a, BStr>>>, + meta: impl Into<OwnShared<file::Metadata>>, + ) -> Result<Self, parse::section::header::Error> { + Ok(Section { + header: parse::section::Header::new(name, subsection)?, + body: Default::default(), + meta: meta.into(), + id: SectionId::default(), + }) + } +} + +/// Access +impl<'a> Section<'a> { + /// Return our header. + pub fn header(&self) -> §ion::Header<'a> { + &self.header + } + + /// Return the unique `id` of the section, for use with the `*_by_id()` family of methods + /// in [gix_config::File][crate::File]. + pub fn id(&self) -> SectionId { + self.id + } + + /// Return our body, containing all keys and values. + pub fn body(&self) -> &Body<'a> { + &self.body + } + + /// Serialize this type into a `BString` for convenience. + /// + /// Note that `to_string()` can also be used, but might not be lossless. + #[must_use] + pub fn to_bstring(&self) -> BString { + let mut buf = Vec::new(); + self.write_to(&mut buf).expect("io error impossible"); + buf.into() + } + + /// Stream ourselves to the given `out`, in order to reproduce this section mostly losslessly + /// as it was parsed. + pub fn write_to(&self, mut out: impl std::io::Write) -> std::io::Result<()> { + self.header.write_to(&mut out)?; + + if self.body.0.is_empty() { + return Ok(()); + } + + let nl = self + .body + .as_ref() + .iter() + .find_map(extract_newline) + .unwrap_or_else(|| platform_newline()); + + if !self + .body + .as_ref() + .iter() + .take_while(|e| !matches!(e, Event::SectionKey(_))) + .any(|e| e.to_bstr_lossy().contains_str(nl)) + { + out.write_all(nl)?; + } + + let mut saw_newline_after_value = true; + let mut in_key_value_pair = false; + for (idx, event) in self.body.as_ref().iter().enumerate() { + match event { + Event::SectionKey(_) => { + if !saw_newline_after_value { + out.write_all(nl)?; + } + saw_newline_after_value = false; + in_key_value_pair = true; + } + Event::Newline(_) if !in_key_value_pair => { + saw_newline_after_value = true; + } + Event::Value(_) | Event::ValueDone(_) => { + in_key_value_pair = false; + } + _ => {} + } + event.write_to(&mut out)?; + if let Event::ValueNotDone(_) = event { + if self + .body + .0 + .get(idx + 1) + .filter(|e| matches!(e, Event::Newline(_))) + .is_none() + { + out.write_all(nl)?; + } + } + } + Ok(()) + } + + /// Return additional information about this sections origin. + pub fn meta(&self) -> &Metadata { + &self.meta + } + + /// Returns a mutable version of this section for adjustment of values. + pub fn to_mut(&mut self, newline: SmallVec<[u8; 2]>) -> SectionMut<'_, 'a> { + SectionMut::new(self, newline) + } +} |