datalog_structural_model/
profile.rs1use crate::{DatalogCapabilities, DatalogFeature, EqualityMode, Program, ProgramValidationError};
3use std::{error::Error, fmt};
4
5#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
8#[serde(deny_unknown_fields)]
9pub struct DatalogProfile {
10 capabilities: DatalogCapabilities,
11 equality_mode: EqualityMode,
12}
13impl DatalogProfile {
14 #[must_use]
17 pub fn new(capabilities: DatalogCapabilities, equality_mode: EqualityMode) -> Self {
18 Self {
19 capabilities,
20 equality_mode,
21 }
22 }
23 #[must_use]
25 pub fn positive() -> Self {
26 Self::new(DatalogCapabilities::positive(), EqualityMode::Default)
27 }
28 #[must_use]
30 pub fn stratified() -> Self {
31 Self::new(
32 DatalogCapabilities::positive().with(DatalogFeature::StratifiedNegation),
33 EqualityMode::Default,
34 )
35 }
36 #[must_use]
38 pub fn capabilities(&self) -> &DatalogCapabilities {
39 &self.capabilities
40 }
41 #[must_use]
43 pub fn equality_mode(&self) -> EqualityMode {
44 self.equality_mode
45 }
46}
47
48#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
50#[serde(deny_unknown_fields)]
51pub struct UnsupportedCapabilities {
52 missing: DatalogCapabilities,
53}
54impl UnsupportedCapabilities {
55 #[must_use]
57 pub fn missing(&self) -> &DatalogCapabilities {
58 &self.missing
59 }
60}
61impl fmt::Display for UnsupportedCapabilities {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 write!(f, "unsupported Datalog features: {:?}", self.missing)
64 }
65}
66impl Error for UnsupportedCapabilities {}
67
68#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
70#[serde(deny_unknown_fields)]
71pub enum ProfileCheckError {
72 InvalidProgram(ProgramValidationError),
74 Unsupported(UnsupportedCapabilities),
76}
77impl fmt::Display for ProfileCheckError {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 match self {
80 Self::InvalidProgram(error) => error.fmt(f),
81 Self::Unsupported(error) => error.fmt(f),
82 }
83 }
84}
85impl Error for ProfileCheckError {
86 fn source(&self) -> Option<&(dyn Error + 'static)> {
87 match self {
88 Self::InvalidProgram(error) => Some(error),
89 Self::Unsupported(error) => Some(error),
90 }
91 }
92}
93impl Program {
94 pub fn validate_for(&self, profile: &DatalogProfile) -> Result<(), ProfileCheckError> {
98 self.validate_with_equality_mode(profile.equality_mode)
99 .map_err(ProfileCheckError::InvalidProgram)?;
100 let missing = self
101 .required_capabilities()
102 .missing_from(&profile.capabilities);
103 if !missing.is_empty() {
104 return Err(ProfileCheckError::Unsupported(UnsupportedCapabilities {
105 missing,
106 }));
107 }
108 Ok(())
109 }
110}