use crate::spec::{Kind, Node};
use crate::{FieldMask, FieldMaskError};
pub(crate) fn validate_mask(mask: &FieldMask, spec: &Node) -> Result<(), FieldMaskError> {
if mask.is_all() {
return Ok(());
}
for p in &mask.paths {
validate_one(p, spec, p.join("."))?;
}
Ok(())
}
pub(crate) fn validate_one(
path: &[String],
spec: &Node,
full: String,
) -> Result<(), FieldMaskError> {
if path.is_empty() {
return Ok(());
}
match &spec.kind {
Kind::Object(map) => {
let key = &path[0];
if key == "*" {
return Err(FieldMaskError::UnknownPath(full));
}
let Some(child) = map.get(key) else {
return Err(FieldMaskError::UnknownPath(full));
};
validate_one(&path[1..], child, full)
}
Kind::Array(elem) | Kind::Map(elem) => {
if path[0] == "*" {
validate_one(&path[1..], elem, full)
} else {
validate_one(path, elem, full)
}
}
Kind::Scalar => {
if path.len() > 1 {
Err(FieldMaskError::UnknownPath(full))
} else {
Ok(())
}
}
}
}