dpp_domain/validation/validator.rs
1//! Runtime-registered product group validator trait and registry — the extensibility
2//! seam for product groups not known to this crate at compile time.
3
4use crate::field_error::FieldError;
5
6/// Trait for runtime-registered product group validators.
7///
8/// Register an implementation in [`ProductGroupValidatorRegistry`] to provide JSON
9/// Schema + cross-field validation for product groups that are not known to this crate
10/// at compile time (e.g., plugin-defined product groups carrying `ProductGroupData::Other`).
11pub trait ProductGroupValidator: Send + Sync {
12 /// Validate the product group payload (the inner data, without the `"productGroup"` tag key).
13 fn validate(&self, data: &serde_json::Value) -> Result<(), Vec<FieldError>>;
14}
15
16/// Registry of runtime product group validators, keyed by catalog product group key.
17///
18/// An empty registry (the default) causes `ProductGroupData::Other` to fail
19/// validation with an "unknown product group" error — silent pass-through is not safe.
20#[derive(Default)]
21pub struct ProductGroupValidatorRegistry {
22 validators: std::collections::HashMap<String, std::sync::Arc<dyn ProductGroupValidator>>,
23}
24
25impl ProductGroupValidatorRegistry {
26 pub fn new() -> Self {
27 Self::default()
28 }
29
30 pub fn register(
31 &mut self,
32 key: impl Into<String>,
33 validator: std::sync::Arc<dyn ProductGroupValidator>,
34 ) {
35 self.validators.insert(key.into(), validator);
36 }
37
38 pub(super) fn get(&self, key: &str) -> Option<&dyn ProductGroupValidator> {
39 self.validators.get(key).map(std::sync::Arc::as_ref)
40 }
41}