#![doc = include_str!("../README.md")]
mod builder;
mod diagnostic;
mod value;
pub use builder::{BuildError, TreeBuilder};
pub use diagnostic::ParseError;
pub use styx_parse::{ParseErrorKind, ScalarKind, Span};
pub use value::{Entry, Object, Payload, Scalar, Sequence, Tag, Value};
pub fn parse(source: &str) -> Result<Value, BuildError> {
let mut parser = styx_parse::Parser::new(source);
let mut builder = TreeBuilder::new();
while let Some(event) = parser.next_event() {
builder.event(event);
}
builder.finish()
}
#[derive(Debug, Clone, PartialEq)]
pub struct Document {
pub root: Object,
pub leading_comments: Vec<String>,
}
impl Document {
pub fn parse(source: &str) -> Result<Self, BuildError> {
let value = parse(source)?;
match value.payload {
Some(Payload::Object(root)) => Ok(Document {
root,
leading_comments: Vec::new(),
}),
_ => Err(BuildError::UnexpectedEvent(
"expected object at root".to_string(),
)),
}
}
pub fn get(&self, path: &str) -> Option<&Value> {
if path.is_empty() {
return None;
}
let (segment, rest) = split_path(path);
let value = self.root.get(segment)?;
if rest.is_empty() {
Some(value)
} else {
value.get(rest)
}
}
}
fn split_path(path: &str) -> (&str, &str) {
if path.starts_with('[')
&& let Some(end) = path.find(']')
{
let segment = &path[..=end];
let rest = &path[end + 1..];
let rest = rest.strip_prefix('.').unwrap_or(rest);
return (segment, rest);
}
let dot_pos = path.find('.');
let bracket_pos = path.find('[');
match (dot_pos, bracket_pos) {
(Some(d), Some(b)) if b < d => (&path[..b], &path[b..]),
(Some(d), _) => (&path[..d], &path[d + 1..]),
(None, Some(b)) => (&path[..b], &path[b..]),
(None, None) => (path, ""),
}
}
#[cfg(test)]
mod tests;