50 lines
1.4 KiB
Rust
50 lines
1.4 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use serde::{Deserialize, Deserializer, de};
|
|
use smartstring::{LazyCompact, SmartString};
|
|
use thiserror::Error;
|
|
|
|
use crate::{Label, objectpath::PathParseError as ObjectPathError};
|
|
|
|
mod parser;
|
|
pub use parser::GroupSegment;
|
|
|
|
#[derive(Debug, Error, PartialEq)]
|
|
pub enum GroupPatternParseError {
|
|
/// A `{` or `}` appeared in an invalid position, or a `{` was never closed.
|
|
#[error("syntax error at index {position}")]
|
|
Syntax { position: usize },
|
|
|
|
/// The contents of a `{...}` block could not be parsed as an object path.
|
|
#[error("invalid object path {path:?}: {source}")]
|
|
InvalidObjectPath {
|
|
start: usize,
|
|
end: usize,
|
|
path: SmartString<LazyCompact>,
|
|
source: ObjectPathError,
|
|
},
|
|
}
|
|
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct GroupPattern {
|
|
pub pattern: HashMap<Label, Vec<GroupSegment>>,
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for GroupPattern {
|
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
let raw = HashMap::<String, String>::deserialize(deserializer)?;
|
|
let mut parts = HashMap::with_capacity(raw.len());
|
|
for (key, value) in raw {
|
|
let label = Label::try_from(key.as_str()).map_err(de::Error::custom)?;
|
|
let segments = parser::Parser::new()
|
|
.parse(&value)
|
|
.map_err(de::Error::custom)?
|
|
.into_iter()
|
|
.map(|(_, seg)| seg)
|
|
.collect();
|
|
parts.insert(label, segments);
|
|
}
|
|
Ok(GroupPattern { pattern: parts })
|
|
}
|
|
}
|