Skip to main content

shex_validation/
validator_config.rs

1use rudof_rdf::rdf_core::RdfDataConfig;
2use serde::{Deserialize, Serialize};
3use shex_ast::ir::external_resolver::{ExternalShapeResolver, ExternalShapeResolverRegistry};
4use shex_ast::shapemap::ShapemapConfig;
5use std::io::Read;
6use std::path::Path;
7use std::sync::Arc;
8
9use crate::{MAX_STEPS, ShExConfig, ValidatorError};
10
11const DEFAULT_WIDTH: usize = 80;
12
13/// This struct can be used to customize the behavour of ShEx validators
14#[derive(Deserialize, Serialize, Debug, Clone)]
15
16pub struct ValidatorConfig {
17    /// Maximum numbers of validation steps
18    pub max_steps: Option<usize>,
19
20    /// Configuration of RDF data readers
21    pub rdf_data: Option<RdfDataConfig>,
22
23    /// Configuration of ShEx schemas
24    pub shex: Option<ShExConfig>,
25
26    /// Configuration of Shapemaps
27    pub shapemap: Option<ShapemapConfig>,
28
29    /// Whether to check the negation requirement (default: true)
30    pub check_negation_requirement: Option<bool>,
31
32    /// Width for pretty printing
33    pub width: Option<usize>,
34
35    /// Resolvers consulted for EXTERNAL shape expressions. Defaults to a
36    /// registry containing only `RejectAllExternalResolver`. Resolvers cannot
37    /// be loaded from TOML — they must be installed programmatically via
38    /// [`Self::with_external_resolver`].
39    #[serde(skip, default)]
40    pub external_resolvers: ExternalShapeResolverRegistry,
41}
42
43impl Default for ValidatorConfig {
44    fn default() -> Self {
45        Self {
46            max_steps: None,
47            rdf_data: Some(RdfDataConfig::default()),
48            shex: Some(ShExConfig::default()),
49            shapemap: Some(ShapemapConfig::default()),
50            check_negation_requirement: Some(true),
51            width: Some(80),
52            external_resolvers: ExternalShapeResolverRegistry::default(),
53        }
54    }
55}
56
57impl ValidatorConfig {
58    /// Obtain a `ValidatorConfig` from a path file in TOML format
59    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<ValidatorConfig, ValidatorError> {
60        let path_name = path.as_ref().display().to_string();
61        let mut f = std::fs::File::open(path).map_err(|e| ValidatorError::ValidatorConfigFromPathError {
62            path: path_name.clone(),
63            error: e.to_string(),
64        })?;
65        let mut s = String::new();
66        f.read_to_string(&mut s)
67            .map_err(|e| ValidatorError::ValidatorConfigFromPathError {
68                path: path_name.clone(),
69                error: e.to_string(),
70            })?;
71
72        let config: ValidatorConfig =
73            toml::from_str(s.as_str()).map_err(|e| ValidatorError::ValidatorConfigTomlError {
74                path: path_name.clone(),
75                error: e.to_string(),
76            })?;
77        Ok(config)
78    }
79
80    pub fn set_max_steps(&mut self, max_steps: usize) {
81        self.max_steps = Some(max_steps);
82    }
83
84    pub fn max_steps(&self) -> usize {
85        self.max_steps.unwrap_or(MAX_STEPS)
86    }
87
88    pub fn rdf_data_config(&self) -> RdfDataConfig {
89        match &self.rdf_data {
90            None => RdfDataConfig::default(),
91            Some(sc) => sc.clone(),
92        }
93    }
94
95    pub fn shex_config(&self) -> ShExConfig {
96        match &self.shex {
97            None => ShExConfig::default(),
98            Some(sc) => sc.clone(),
99        }
100    }
101
102    pub fn shapemap_config(&self) -> ShapemapConfig {
103        match &self.shapemap {
104            None => ShapemapConfig::default(),
105            Some(sc) => sc.clone(),
106        }
107    }
108
109    pub fn width(&self) -> usize {
110        match self.width {
111            None => DEFAULT_WIDTH,
112            Some(w) => w,
113        }
114    }
115
116    pub fn set_check_negation_requirement(&mut self, check: bool) {
117        self.check_negation_requirement = Some(check);
118    }
119
120    pub fn external_resolvers(&self) -> &ExternalShapeResolverRegistry {
121        &self.external_resolvers
122    }
123
124    /// Prepend a resolver to the EXTERNAL-shape resolver chain. Returns the
125    /// updated config for builder-style chaining.
126    pub fn with_external_resolver<R: ExternalShapeResolver + 'static>(mut self, r: R) -> Self {
127        self.external_resolvers = std::mem::take(&mut self.external_resolvers).with_resolver(r);
128        self
129    }
130
131    pub fn with_external_resolver_arc(mut self, r: Arc<dyn ExternalShapeResolver>) -> Self {
132        self.external_resolvers = std::mem::take(&mut self.external_resolvers).with_resolver_arc(r);
133        self
134    }
135}