Skip to main content

sim_relation_core/
names.rs

1use sim_kernel::Symbol;
2use std::fmt;
3
4/// Validation failure for a relational symbolic name.
5#[derive(Clone, Debug, PartialEq, Eq)]
6pub enum NameError {
7    /// A symbol component was empty.
8    Empty,
9    /// A symbol component contained a control character.
10    Control,
11}
12
13impl fmt::Display for NameError {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        f.write_str(match self {
16            Self::Empty => "relational names cannot be empty",
17            Self::Control => "relational names cannot contain control characters",
18        })
19    }
20}
21impl std::error::Error for NameError {}
22
23fn validate(symbol: &Symbol) -> Result<(), NameError> {
24    if symbol.name.is_empty() || symbol.namespace.as_ref().is_some_and(|v| v.is_empty()) {
25        return Err(NameError::Empty);
26    }
27    if symbol.name.chars().any(char::is_control)
28        || symbol
29            .namespace
30            .as_ref()
31            .is_some_and(|v| v.chars().any(char::is_control))
32    {
33        return Err(NameError::Control);
34    }
35    Ok(())
36}
37
38macro_rules! name_type {
39    ($name:ident, $doc:literal) => {
40        #[doc = $doc]
41        #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
42        pub struct $name(Symbol);
43        impl $name {
44            /// Validates and constructs the name. SQL punctuation and keywords are accepted.
45            pub fn new(symbol: Symbol) -> Result<Self, NameError> {
46                validate(&symbol)?;
47                Ok(Self(symbol))
48            }
49            /// Returns the underlying open symbol.
50            pub fn symbol(&self) -> &Symbol {
51                &self.0
52            }
53        }
54        impl TryFrom<Symbol> for $name {
55            type Error = NameError;
56            fn try_from(value: Symbol) -> Result<Self, Self::Error> {
57                Self::new(value)
58            }
59        }
60        impl From<$name> for Symbol {
61            fn from(value: $name) -> Self {
62                value.0
63            }
64        }
65    };
66}
67
68name_type!(TableName, "A table name.");
69name_type!(ColumnName, "A column name.");
70name_type!(SourceName, "A relational source name.");
71name_type!(BindingName, "A query binding name.");
72name_type!(FieldName, "A projected field name.");
73name_type!(ParameterName, "A parameter name.");
74name_type!(ConstraintName, "A constraint name.");
75name_type!(IndexName, "An index name.");
76name_type!(RevisionName, "A revision name.");
77name_type!(ProviderName, "A storage provider name.");
78name_type!(DomainId, "An open logical-domain identifier.");
79name_type!(SchemaName, "A logical schema name.");
80name_type!(ViewName, "A relational view name.");