use bstr::{BStr, BString, ByteSlice};
mod from_bytes;
mod event;
#[path = "events.rs"]
mod events_type;
pub(crate) use events_type::FrontMatterEvents;
pub use events_type::{Events, SectionRef};
mod comment;
mod error;
pub mod section;
#[cfg(test)]
pub(crate) mod tests;
#[derive(Copy, Clone, Debug, Default)]
pub(crate) struct Span {
start: u32,
len: u32,
}
pub mod span {
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, thiserror::Error)]
#[error("configuration data exceeds the supported span size of {} bytes", u32::MAX)]
pub struct Error;
}
#[derive(Clone, Debug)]
pub(crate) struct MaybeDecoded {
raw: Span,
decoded: Option<BString>,
}
impl MaybeDecoded {
pub(crate) fn raw(raw: Span) -> Self {
Self { raw, decoded: None }
}
pub(crate) fn decoded(raw: Span, decoded: BString) -> Self {
Self {
raw,
decoded: Some(decoded),
}
}
pub(crate) fn raw_span(&self) -> Span {
self.raw
}
pub(crate) fn value_in<'a>(&'a self, backing: &'a [u8]) -> &'a BStr {
self.decoded
.as_ref()
.map_or_else(|| self.raw.as_bstr_in(backing), |value| value.as_bstr())
}
pub(crate) fn rebase(&mut self, offset: usize) -> Result<(), span::Error> {
self.raw.rebase(offset)
}
pub(crate) fn copy_to_backing_in(&self, source: &[u8], target: &mut Vec<u8>) -> Result<Self, span::Error> {
Ok(Self {
raw: self.raw.copy_to_backing_in(source, target)?,
decoded: self.decoded.clone(),
})
}
}
impl Span {
pub(crate) fn append(backing: &mut Vec<u8>, bytes: &[u8]) -> Result<Self, span::Error> {
let start = backing.len();
let span = Self::range(start, bytes.len())?;
backing.len().checked_add(bytes.len()).ok_or(span::Error)?;
backing.extend_from_slice(bytes);
Ok(span)
}
pub(crate) fn range(start: usize, len: usize) -> Result<Self, span::Error> {
Ok(Span {
start: start.try_into().map_err(|_| span::Error)?,
len: len.try_into().map_err(|_| span::Error)?,
})
}
pub(crate) fn new(backing: &[u8], bytes: &[u8]) -> Self {
if bytes.is_empty() {
return Self::default();
}
debug_assert!(!backing.is_empty());
let base = backing.as_ptr() as usize;
let start = (bytes.as_ptr() as usize)
.checked_sub(base)
.expect("span must point into the backing buffer");
let end = start + bytes.len();
debug_assert!(end <= backing.len());
Self::range(start, bytes.len()).expect("the parser rejects backing buffers that exceed the span limit")
}
pub fn as_bstr_in<'a>(&'a self, backing: &'a [u8]) -> &'a BStr {
self.as_slice_in(backing).as_bstr()
}
pub fn as_slice_in<'a>(&'a self, backing: &'a [u8]) -> &'a [u8] {
let start = self.start as usize;
&backing[start..start + self.len as usize]
}
pub fn to_bstring_in(self, backing: &[u8]) -> BString {
self.as_slice_in(backing).into()
}
pub(crate) fn copy_to_backing_in(&self, source: &[u8], target: &mut Vec<u8>) -> Result<Self, span::Error> {
Span::append(target, self.as_slice_in(source))
}
pub(crate) fn rebase(&mut self, offset: usize) -> Result<(), span::Error> {
self.start = (self.start as usize)
.checked_add(offset)
.and_then(|start| start.try_into().ok())
.ok_or(span::Error)?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub(crate) enum Event {
Comment(Comment),
SectionHeader(section::HeaderData),
SectionValueName(Span),
Value(Span),
Newline(Span),
ValueNotDone(Span),
ValueDone(Span),
Whitespace(Span),
KeyValueSeparator,
}
#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum EventRef<'a> {
Comment {
tag: u8,
text: &'a BStr,
},
SectionHeader {
name: &'a BStr,
separator: Option<&'a BStr>,
subsection_name: Option<&'a BStr>,
},
SectionValueName(&'a BStr),
Value(&'a BStr),
Newline(&'a BStr),
ValueNotDone(&'a BStr),
ValueDone(&'a BStr),
Whitespace(&'a BStr),
KeyValueSeparator,
}
#[derive(Clone, Debug)]
pub(crate) struct SectionData {
pub(crate) header: section::HeaderData,
pub(crate) events: Vec<Event>,
}
#[derive(Clone, Debug, Default)]
pub(crate) struct Comment {
pub(crate) tag: u8,
pub(crate) text: Span,
}
#[derive(PartialEq, Debug)]
pub struct Error {
kind: error::Kind,
}