#[doc(hidden)]
#[macro_use]
pub mod internal_prelude;
#[macro_use]
mod structural;
#[macro_use]
mod derive;
mod error;
mod impls;
pub mod keyword;
mod lex;
mod lines;
pub mod multiplicity;
mod signatures;
mod traits;
#[cfg(feature = "plain-consensus")]
pub mod poc;
use internal_prelude::*;
pub use error::{ArgumentError, ErrorProblem, ParseError, UnexpectedArgument, VerifyFailed};
pub use impls::raw_data_object;
pub use impls::times::NdaSystemTimeDeprecatedSyntax;
pub use keyword::KeywordRef;
pub use lex::{ArgumentStream, ItemStream, NoFurtherArguments, UnparsedItem, UnparsedObject};
pub use lines::{Lines, Peeked, StrExt};
pub use signatures::{
HasUnverifiedParsedBody, NetdocParseableSignatures, NetdocUnverified, SignatureHashInputs,
SignatureHashesAccumulator, SignatureItemParseable, SignaturesData, check_validity_time,
check_validity_time_tolerance, sig_hashes,
};
pub use structural::{StopAt, StopPredicate};
pub use traits::{
IsStructural, ItemArgumentParseable, ItemObjectParseable, ItemValueParseable, NetdocParseable,
NetdocParseableFields,
};
#[doc(hidden)]
pub use derive::netdoc_parseable_derive_debug;
pub(crate) use internal_prelude::EP;
#[derive(educe::Educe, Debug, Clone)]
#[allow(clippy::manual_non_exhaustive)]
#[educe(Default)]
pub struct ParseOptions {
#[educe(Default(expression = "Unknown::new_discard()"))]
pub retain_unknown_values: Unknown<()>,
#[doc(hidden)]
_private_non_exhaustive: (),
}
pub struct ParseInput<'s> {
input: &'s str,
file: &'s str,
options: ParseOptions,
}
impl<'s> ParseInput<'s> {
pub fn new(input: &'s str, file: &'s str) -> Self {
ParseInput {
input,
file,
options: ParseOptions::default(),
}
}
}
fn parse_internal<T, D: NetdocParseable>(
input: &ParseInput<'_>,
parse_completely: impl FnOnce(&mut ItemStream) -> Result<T, ErrorProblem>,
) -> Result<T, ParseError> {
let mut items = ItemStream::new(input)?;
parse_completely(&mut items).map_err(|problem| ParseError {
problem,
doctype: D::doctype_for_error(),
file: input.file.to_owned(),
lno: items.lno_for_error(),
column: problem.column(),
})
}
pub fn parse_netdoc<D: NetdocParseable>(input: &ParseInput<'_>) -> Result<D, ParseError> {
parse_internal::<_, D>(input, |items| {
let doc = D::from_items(items, StopAt(false))?;
if let Some(_kw) = items.peek_keyword()? {
return Err(EP::MultipleDocuments);
}
Ok(doc)
})
}
pub fn parse_netdoc_multiple<D: NetdocParseable>(
input: &ParseInput<'_>,
) -> Result<Vec<D>, ParseError> {
parse_internal::<_, D>(input, |items| {
let mut docs = vec![];
while items.peek_keyword()?.is_some() {
let doc = D::from_items(items, StopAt(false))?;
docs.push(doc);
}
Ok(docs)
})
}
pub fn parse_netdoc_multiple_with_offsets<D: NetdocParseable>(
input: &ParseInput<'_>,
) -> Result<Vec<(D, usize, usize)>, ParseError> {
parse_internal::<_, D>(input, |items| {
let mut docs = vec![];
while items.peek_keyword()?.is_some() {
let start_pos = items.byte_position();
let doc = D::from_items(items, StopAt(false))?;
let end_pos = items.byte_position();
if input.input.get(start_pos..end_pos).is_none() {
return Err(ErrorProblem::Internal("out-of-bounds bug?"));
}
docs.push((doc, start_pos, end_pos));
}
Ok(docs)
})
}