diff --git a/README.md b/README.md index c9b964fb..ae9a1a76 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ This is the lowest-level Mentat crate. It collects together the following things - Fundamental domain-specific data structures like `ValueType` and `TypedValue`. - Fundamental SQL-related linkages like `SQLValueType`. These encode the mapping between Mentat's types and values and their representation in our SQLite format. -- Conversion to and from EDN types (_e.g._, `edn::NamespacedKeyword` to `TypedValue::Keyword`). +- Conversion to and from EDN types (_e.g._, `edn::Keyword` to `TypedValue::Keyword`). - Common utilities (some in the `util` module, and others that should be moved there or broken out) like `Either`, `InternSet`, and `RcCounter`. - Reusable lazy namespaced keywords (_e.g._, `DB_TYPE_DOUBLE`) that are used by `mentat_db` and EDN serialization of core structs. diff --git a/core/src/lib.rs b/core/src/lib.rs index 6353833f..bf2446c8 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -39,7 +39,7 @@ pub use chrono::{ pub use edn::{ FromMicros, - NamespacedKeyword, + Keyword, ToMicros, Utc, }; @@ -180,10 +180,10 @@ impl Attribute { flags } - pub fn to_edn_value(&self, ident: Option) -> edn::Value { + pub fn to_edn_value(&self, ident: Option) -> edn::Value { let mut attribute_map: BTreeMap = BTreeMap::default(); if let Some(ident) = ident { - attribute_map.insert(values::DB_IDENT.clone(), edn::Value::NamespacedKeyword(ident)); + attribute_map.insert(values::DB_IDENT.clone(), edn::Value::Keyword(ident)); } attribute_map.insert(values::DB_VALUE_TYPE.clone(), self.value_type.into_edn_value()); @@ -231,11 +231,11 @@ impl Default for Attribute { } } -/// Map `NamespacedKeyword` idents (`:db/ident`) to positive integer entids (`1`). -pub type IdentMap = BTreeMap; +/// Map `Keyword` idents (`:db/ident`) to positive integer entids (`1`). +pub type IdentMap = BTreeMap; -/// Map positive integer entids (`1`) to `NamespacedKeyword` idents (`:db/ident`). -pub type EntidMap = BTreeMap; +/// Map positive integer entids (`1`) to `Keyword` idents (`:db/ident`). +pub type EntidMap = BTreeMap; /// Map attribute entids to `Attribute` instances. pub type AttributeMap = BTreeMap; @@ -273,18 +273,18 @@ pub struct Schema { pub trait HasSchema { fn entid_for_type(&self, t: ValueType) -> Option; - fn get_ident(&self, x: T) -> Option<&NamespacedKeyword> where T: Into; - fn get_entid(&self, x: &NamespacedKeyword) -> Option; + fn get_ident(&self, x: T) -> Option<&Keyword> where T: Into; + fn get_entid(&self, x: &Keyword) -> Option; fn attribute_for_entid(&self, x: T) -> Option<&Attribute> where T: Into; // Returns the attribute and the entid named by the provided ident. - fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<(&Attribute, KnownEntid)>; + fn attribute_for_ident(&self, ident: &Keyword) -> Option<(&Attribute, KnownEntid)>; /// Return true if the provided entid identifies an attribute in this schema. fn is_attribute(&self, x: T) -> bool where T: Into; /// Return true if the provided ident identifies an attribute in this schema. - fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool; + fn identifies_attribute(&self, x: &Keyword) -> bool; fn component_attributes(&self) -> &[Entid]; } @@ -304,7 +304,7 @@ impl Schema { .collect()) } - fn get_raw_entid(&self, x: &NamespacedKeyword) -> Option { + fn get_raw_entid(&self, x: &Keyword) -> Option { self.ident_map.get(x).map(|x| *x) } @@ -325,11 +325,11 @@ impl HasSchema for Schema { self.get_entid(&t.into_keyword()) } - fn get_ident(&self, x: T) -> Option<&NamespacedKeyword> where T: Into { + fn get_ident(&self, x: T) -> Option<&Keyword> where T: Into { self.entid_map.get(&x.into()) } - fn get_entid(&self, x: &NamespacedKeyword) -> Option { + fn get_entid(&self, x: &Keyword) -> Option { self.get_raw_entid(x).map(KnownEntid) } @@ -337,7 +337,7 @@ impl HasSchema for Schema { self.attribute_map.get(&x.into()) } - fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<(&Attribute, KnownEntid)> { + fn attribute_for_ident(&self, ident: &Keyword) -> Option<(&Attribute, KnownEntid)> { self.get_raw_entid(&ident) .and_then(|entid| { self.attribute_for_entid(entid).map(|a| (a, KnownEntid(entid))) @@ -350,7 +350,7 @@ impl HasSchema for Schema { } /// Return true if the provided ident identifies an attribute in this schema. - fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool { + fn identifies_attribute(&self, x: &Keyword) -> bool { self.get_raw_entid(x).map(|e| self.is_attribute(e)).unwrap_or(false) } @@ -408,7 +408,7 @@ mod test { use std::str::FromStr; - fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) { + fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) { schema.entid_map.insert(e, i.clone()); schema.ident_map.insert(i, e); } @@ -491,7 +491,7 @@ mod test { component: false, no_history: true, }; - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 97); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 97); add_attribute(&mut schema, 97, attr1); let attr2 = Attribute { @@ -503,7 +503,7 @@ mod test { component: false, no_history: false, }; - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bas"), 98); + associate_ident(&mut schema, Keyword::namespaced("foo", "bas"), 98); add_attribute(&mut schema, 98, attr2); let attr3 = Attribute { @@ -516,7 +516,7 @@ mod test { no_history: false, }; - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bat"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bat"), 99); add_attribute(&mut schema, 99, attr3); let value = schema.to_edn_value(); diff --git a/core/src/types.rs b/core/src/types.rs index ff9fb33e..01690b34 100644 --- a/core/src/types.rs +++ b/core/src/types.rs @@ -40,7 +40,7 @@ use ::indexmap::{ use ::edn::{ self, FromMicros, - NamespacedKeyword, + Keyword, Utc, }; @@ -205,8 +205,8 @@ impl ::enum_set::CLike for ValueType { } impl ValueType { - pub fn into_keyword(self) -> NamespacedKeyword { - NamespacedKeyword::new("db.type", match self { + pub fn into_keyword(self) -> Keyword { + Keyword::namespaced("db.type", match self { ValueType::Ref => "ref", ValueType::Boolean => "boolean", ValueType::Instant => "instant", @@ -280,7 +280,7 @@ pub enum TypedValue { Instant(DateTime), // Use `into()` to ensure truncation. // TODO: &str throughout? String(ValueRc), - Keyword(ValueRc), + Keyword(ValueRc), Uuid(Uuid), // It's only 128 bits, so this should be acceptable to clone. } @@ -335,23 +335,23 @@ impl Binding { /// We entirely support the former, and partially support the latter -- you can alias /// using a different keyword only. #[derive(Clone, Debug, Default, Eq, PartialEq)] -pub struct StructuredMap(pub IndexMap, Binding>); +pub struct StructuredMap(pub IndexMap, Binding>); impl StructuredMap { - pub fn insert(&mut self, name: N, value: B) where N: Into>, B: Into { + pub fn insert(&mut self, name: N, value: B) where N: Into>, B: Into { self.0.insert(name.into(), value.into()); } } -impl From, Binding>> for StructuredMap { - fn from(src: IndexMap, Binding>) -> Self { +impl From, Binding>> for StructuredMap { + fn from(src: IndexMap, Binding>) -> Self { StructuredMap(src) } } // Mostly for testing. -impl From> for StructuredMap where T: Into { - fn from(value: Vec<(NamespacedKeyword, T)>) -> Self { +impl From> for StructuredMap where T: Into { + fn from(value: Vec<(Keyword, T)>) -> Self { let mut sm = StructuredMap::default(); for (k, v) in value.into_iter() { sm.insert(k, v); @@ -414,7 +414,7 @@ impl TypedValue { /// values and wrapping them in a new `ValueRc`. This is expensive, so this might /// be best limited to tests. pub fn typed_ns_keyword(ns: &str, name: &str) -> TypedValue { - NamespacedKeyword::new(ns, name).into() + Keyword::namespaced(ns, name).into() } /// Construct a new `TypedValue::String` instance by cloning the provided @@ -509,20 +509,20 @@ impl From for TypedValue { } } -impl From> for TypedValue { - fn from(value: Arc) -> TypedValue { +impl From> for TypedValue { + fn from(value: Arc) -> TypedValue { TypedValue::Keyword(ValueRc::from_arc(value)) } } -impl From> for TypedValue { - fn from(value: Rc) -> TypedValue { +impl From> for TypedValue { + fn from(value: Rc) -> TypedValue { TypedValue::Keyword(ValueRc::from_rc(value)) } } -impl From for TypedValue { - fn from(value: NamespacedKeyword) -> TypedValue { +impl From for TypedValue { + fn from(value: Keyword) -> TypedValue { TypedValue::Keyword(ValueRc::new(value)) } } @@ -560,7 +560,7 @@ impl TypedValue { } } - pub fn into_kw(self) -> Option> { + pub fn into_kw(self) -> Option> { match self { TypedValue::Keyword(v) => Some(v), _ => None, @@ -687,7 +687,7 @@ impl Binding { } } - pub fn into_kw(self) -> Option> { + pub fn into_kw(self) -> Option> { match self { Binding::Scalar(TypedValue::Keyword(v)) => Some(v), _ => None, diff --git a/core/src/values.rs b/core/src/values.rs index e8eb2ba7..555e4098 100644 --- a/core/src/values.rs +++ b/core/src/values.rs @@ -17,7 +17,7 @@ use edn::types::Value; use edn::symbols; -/// Declare a lazy static `ident` of type `Value::NamespacedKeyword` with the given `namespace` and +/// Declare a lazy static `ident` of type `Value::Keyword` with the given `namespace` and /// `name`. /// /// It may look surprising that we declare a new `lazy_static!` block rather than including @@ -31,7 +31,7 @@ macro_rules! lazy_static_namespaced_keyword_value ( ($tag:ident, $namespace:expr, $name:expr) => ( lazy_static! { pub static ref $tag: Value = { - Value::NamespacedKeyword(symbols::NamespacedKeyword::new($namespace, $name)) + Value::Keyword(symbols::Keyword::namespaced($namespace, $name)) }; } ) diff --git a/db/src/bootstrap.rs b/db/src/bootstrap.rs index 758c2127..c35f041c 100644 --- a/db/src/bootstrap.rs +++ b/db/src/bootstrap.rs @@ -38,7 +38,7 @@ pub const USER0: i64 = 0x10000; pub const CORE_SCHEMA_VERSION: u32 = 1; lazy_static! { - static ref V1_IDENTS: [(symbols::NamespacedKeyword, i64); 40] = { + static ref V1_IDENTS: [(symbols::Keyword, i64); 40] = { [(ns_keyword!("db", "ident"), entids::DB_IDENT), (ns_keyword!("db.part", "db"), entids::DB_PART_DB), (ns_keyword!("db", "txInstant"), entids::DB_TX_INSTANT), @@ -82,14 +82,14 @@ lazy_static! { ] }; - static ref V1_PARTS: [(symbols::NamespacedKeyword, i64, i64); 3] = { + static ref V1_PARTS: [(symbols::Keyword, i64, i64); 3] = { [(ns_keyword!("db.part", "db"), 0, (1 + V1_IDENTS.len()) as i64), (ns_keyword!("db.part", "user"), USER0, USER0), (ns_keyword!("db.part", "tx"), TX0, TX0), ] }; - static ref V1_CORE_SCHEMA: [(symbols::NamespacedKeyword); 16] = { + static ref V1_CORE_SCHEMA: [(symbols::Keyword); 16] = { [(ns_keyword!("db", "ident")), (ns_keyword!("db.install", "partition")), (ns_keyword!("db.install", "valueType")), @@ -162,25 +162,25 @@ lazy_static! { } /// Convert (ident, entid) pairs into [:db/add IDENT :db/ident IDENT] `Value` instances. -fn idents_to_assertions(idents: &[(symbols::NamespacedKeyword, i64)]) -> Vec { +fn idents_to_assertions(idents: &[(symbols::Keyword, i64)]) -> Vec { idents .into_iter() .map(|&(ref ident, _)| { - let value = Value::NamespacedKeyword(ident.clone()); + let value = Value::Keyword(ident.clone()); Value::Vector(vec![values::DB_ADD.clone(), value.clone(), values::DB_IDENT.clone(), value.clone()]) }) .collect() } /// Convert an ident list into [:db/add :db.schema/core :db.schema/attribute IDENT] `Value` instances. -fn schema_attrs_to_assertions(version: u32, idents: &[symbols::NamespacedKeyword]) -> Vec { - let schema_core = Value::NamespacedKeyword(ns_keyword!("db.schema", "core")); - let schema_attr = Value::NamespacedKeyword(ns_keyword!("db.schema", "attribute")); - let schema_version = Value::NamespacedKeyword(ns_keyword!("db.schema", "version")); +fn schema_attrs_to_assertions(version: u32, idents: &[symbols::Keyword]) -> Vec { + let schema_core = Value::Keyword(ns_keyword!("db.schema", "core")); + let schema_attr = Value::Keyword(ns_keyword!("db.schema", "attribute")); + let schema_version = Value::Keyword(ns_keyword!("db.schema", "version")); idents .into_iter() .map(|ident| { - let value = Value::NamespacedKeyword(ident.clone()); + let value = Value::Keyword(ident.clone()); Value::Vector(vec![values::DB_ADD.clone(), schema_core.clone(), schema_attr.clone(), @@ -194,28 +194,28 @@ fn schema_attrs_to_assertions(version: u32, idents: &[symbols::NamespacedKeyword } /// Convert {:ident {:key :value ...} ...} to -/// vec![(symbols::NamespacedKeyword(:ident), symbols::NamespacedKeyword(:key), TypedValue(:value)), ...]. +/// vec![(symbols::Keyword(:ident), symbols::Keyword(:key), TypedValue(:value)), ...]. /// /// Such triples are closer to what the transactor will produce when processing attribute /// assertions. -fn symbolic_schema_to_triples(ident_map: &IdentMap, symbolic_schema: &Value) -> Result> { +fn symbolic_schema_to_triples(ident_map: &IdentMap, symbolic_schema: &Value) -> Result> { // Failure here is a coding error, not a runtime error. - let mut triples: Vec<(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)> = vec![]; + let mut triples: Vec<(symbols::Keyword, symbols::Keyword, TypedValue)> = vec![]; // TODO: Consider `flat_map` and `map` rather than loop. match *symbolic_schema { Value::Map(ref m) => { for (ident, mp) in m { let ident = match ident { - &Value::NamespacedKeyword(ref ident) => ident, - _ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for ident but got '{:?}'", ident))) + &Value::Keyword(ref ident) => ident, + v => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for ident but got '{:?}'", ident))), }; match *mp { Value::Map(ref mpp) => { for (attr, value) in mpp { let attr = match attr { - &Value::NamespacedKeyword(ref attr) => attr, - _ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for attr but got '{:?}'", attr))) - }; + &Value::Keyword(ref attr) => attr, + _ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for attr but got '{:?}'", attr))), + }; // We have symbolic idents but the transactor handles entids. Ad-hoc // convert right here. This is a fundamental limitation on the @@ -286,19 +286,19 @@ pub(crate) fn bootstrap_ident_map() -> IdentMap { pub(crate) fn bootstrap_schema() -> Schema { let ident_map = bootstrap_ident_map(); - let bootstrap_triples = symbolic_schema_to_triples(&ident_map, &V1_SYMBOLIC_SCHEMA).unwrap(); + let bootstrap_triples = symbolic_schema_to_triples(&ident_map, &V1_SYMBOLIC_SCHEMA).expect("symbolic schema"); Schema::from_ident_map_and_triples(ident_map, bootstrap_triples).unwrap() } pub(crate) fn bootstrap_entities() -> Vec { let bootstrap_assertions: Value = Value::Vector([ - symbolic_schema_to_assertions(&V1_SYMBOLIC_SCHEMA).unwrap(), + symbolic_schema_to_assertions(&V1_SYMBOLIC_SCHEMA).expect("symbolic schema"), idents_to_assertions(&V1_IDENTS[..]), schema_attrs_to_assertions(CORE_SCHEMA_VERSION, V1_CORE_SCHEMA.as_ref()), ].concat()); // Failure here is a coding error (since the inputs are fixed), not a runtime error. // TODO: represent these bootstrap data errors rather than just panicing. - let bootstrap_entities: Vec = edn::parse::entities(&bootstrap_assertions.to_string()).unwrap(); + let bootstrap_entities: Vec = edn::parse::entities(&bootstrap_assertions.to_string()).expect("bootstrap assertions"); return bootstrap_entities; } diff --git a/db/src/db.rs b/db/src/db.rs index 58729ccb..fe87b002 100644 --- a/db/src/db.rs +++ b/db/src/db.rs @@ -422,7 +422,7 @@ impl TypedSQLValue for TypedValue { &Value::Uuid(x) => Some(TypedValue::Uuid(x)), &Value::Float(ref x) => Some(TypedValue::Double(x.clone())), &Value::Text(ref x) => Some(x.clone().into()), - &Value::NamespacedKeyword(ref x) => Some(x.clone().into()), + &Value::Keyword(ref x) => Some(x.clone().into()), _ => None } } @@ -452,7 +452,7 @@ impl TypedSQLValue for TypedValue { &TypedValue::Double(x) => (Value::Float(x), ValueType::Double), &TypedValue::String(ref x) => (Value::Text(x.as_ref().clone()), ValueType::String), &TypedValue::Uuid(ref u) => (Value::Uuid(u.clone()), ValueType::Uuid), - &TypedValue::Keyword(ref x) => (Value::NamespacedKeyword(x.as_ref().clone()), ValueType::Keyword), + &TypedValue::Keyword(ref x) => (Value::Keyword(x.as_ref().clone()), ValueType::Keyword), } } } @@ -1155,7 +1155,7 @@ mod tests { use edn; use mentat_core::{ HasSchema, - NamespacedKeyword, + Keyword, Schema, attribute, }; @@ -1840,7 +1840,7 @@ mod tests { // Once we've done so, the schema shows it's not unique… { - let attr = conn.schema.attribute_for_ident(&NamespacedKeyword::new("test", "ident")).unwrap().0; + let attr = conn.schema.attribute_for_ident(&Keyword::namespaced("test", "ident")).unwrap().0; assert_eq!(None, attr.unique); } diff --git a/db/src/debug.rs b/db/src/debug.rs index 403713b9..70e9b1d2 100644 --- a/db/src/debug.rs +++ b/db/src/debug.rs @@ -71,7 +71,7 @@ impl Datom { let f = |entid: &Entid| -> edn::Value { match *entid { Entid::Entid(ref y) => edn::Value::Integer(y.clone()), - Entid::Ident(ref y) => edn::Value::NamespacedKeyword(y.clone()), + Entid::Ident(ref y) => edn::Value::Keyword(y.clone()), } }; diff --git a/db/src/internal_types.rs b/db/src/internal_types.rs index 6766d831..a65c06a4 100644 --- a/db/src/internal_types.rs +++ b/db/src/internal_types.rs @@ -73,7 +73,14 @@ impl TransactableValue for ValueAndSpan { use self::SpannedValue::*; match self.inner { Integer(v) => Ok(EntidOrLookupRefOrTempId::Entid(entities::Entid::Entid(v))), - NamespacedKeyword(v) => Ok(EntidOrLookupRefOrTempId::Entid(entities::Entid::Ident(v))), + Keyword(v) => { + if v.is_namespaced() { + Ok(EntidOrLookupRefOrTempId::Entid(entities::Entid::Ident(v))) + } else { + // We only allow namespaced idents. + bail!(ErrorKind::InputError(errors::InputError::BadEntityPlace)) + } + }, Text(v) => Ok(EntidOrLookupRefOrTempId::TempId(TempId::External(v))), List(ls) => { let mut it = ls.iter(); @@ -102,7 +109,6 @@ impl TransactableValue for ValueAndSpan { Uuid(_) | PlainSymbol(_) | NamespacedSymbol(_) | - Keyword(_) | Vector(_) | Set(_) | Map(_) => bail!(ErrorKind::InputError(errors::InputError::BadEntityPlace)), diff --git a/db/src/lib.rs b/db/src/lib.rs index 9652a342..d5cf0476 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -98,16 +98,16 @@ pub use types::{ TxReport, }; -pub fn to_namespaced_keyword(s: &str) -> Result { +pub fn to_namespaced_keyword(s: &str) -> Result { let splits = [':', '/']; let mut i = s.split(&splits[..]); let nsk = match (i.next(), i.next(), i.next(), i.next()) { - (Some(""), Some(namespace), Some(name), None) => Some(symbols::NamespacedKeyword::new(namespace, name)), + (Some(""), Some(namespace), Some(name), None) => Some(symbols::Keyword::namespaced(namespace, name)), _ => None, }; // TODO Use custom ErrorKind https://github.com/brson/error-chain/issues/117 - nsk.ok_or(ErrorKind::NotYetImplemented(format!("InvalidNamespacedKeyword: {}", s)).into()) + nsk.ok_or(ErrorKind::NotYetImplemented(format!("InvalidKeyword: {}", s)).into()) } /// Prepare an SQL `VALUES` block, like (?, ?, ?), (?, ?, ?). diff --git a/db/src/metadata.rs b/db/src/metadata.rs index 953a7bd6..9ac02067 100644 --- a/db/src/metadata.rs +++ b/db/src/metadata.rs @@ -72,7 +72,7 @@ pub enum AttributeAlteration { /// An alteration to an ident. #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] pub enum IdentAlteration { - Ident(symbols::NamespacedKeyword), + Ident(symbols::Keyword), } /// Summarizes changes to metadata such as a a `Schema` and (in the future) a `PartitionMap`. @@ -285,7 +285,7 @@ pub fn update_schema_from_entid_quadruples(schema: &mut Schema, assertions: U // retracted at most once), which means all attribute alterations are simple changes from an old // value to a new value. let mut attribute_set: AddRetractAlterSet<(Entid, Entid), TypedValue> = AddRetractAlterSet::default(); - let mut ident_set: AddRetractAlterSet = AddRetractAlterSet::default(); + let mut ident_set: AddRetractAlterSet = AddRetractAlterSet::default(); for (e, a, typed_value, added) in assertions.into_iter() { // Here we handle :db/ident assertions. diff --git a/db/src/schema.rs b/db/src/schema.rs index bfa6589b..8ff2c19f 100644 --- a/db/src/schema.rs +++ b/db/src/schema.rs @@ -237,20 +237,20 @@ impl AttributeBuilder { } pub trait SchemaBuilding { - fn require_ident(&self, entid: Entid) -> Result<&symbols::NamespacedKeyword>; - fn require_entid(&self, ident: &symbols::NamespacedKeyword) -> Result; + fn require_ident(&self, entid: Entid) -> Result<&symbols::Keyword>; + fn require_entid(&self, ident: &symbols::Keyword) -> Result; fn require_attribute_for_entid(&self, entid: Entid) -> Result<&Attribute>; fn from_ident_map_and_attribute_map(ident_map: IdentMap, attribute_map: AttributeMap) -> Result; fn from_ident_map_and_triples(ident_map: IdentMap, assertions: U) -> Result - where U: IntoIterator; + where U: IntoIterator; } impl SchemaBuilding for Schema { - fn require_ident(&self, entid: Entid) -> Result<&symbols::NamespacedKeyword> { + fn require_ident(&self, entid: Entid) -> Result<&symbols::Keyword> { self.get_ident(entid).ok_or(ErrorKind::UnrecognizedEntid(entid).into()) } - fn require_entid(&self, ident: &symbols::NamespacedKeyword) -> Result { + fn require_entid(&self, ident: &symbols::Keyword) -> Result { self.get_entid(&ident).ok_or(ErrorKind::UnrecognizedIdent(ident.to_string()).into()) } @@ -266,9 +266,9 @@ impl SchemaBuilding for Schema { Ok(Schema::new(ident_map, entid_map, attribute_map)) } - /// Turn vec![(NamespacedKeyword(:ident), NamespacedKeyword(:key), TypedValue(:value)), ...] into a Mentat `Schema`. + /// Turn vec![(Keyword(:ident), Keyword(:key), TypedValue(:value)), ...] into a Mentat `Schema`. fn from_ident_map_and_triples(ident_map: IdentMap, assertions: U) -> Result - where U: IntoIterator{ + where U: IntoIterator{ let entid_assertions: Result> = assertions.into_iter().map(|(symbolic_ident, symbolic_attr, value)| { let ident: i64 = *ident_map.get(&symbolic_ident).ok_or(ErrorKind::UnrecognizedIdent(symbolic_ident.to_string()))?; @@ -342,11 +342,11 @@ impl SchemaTypeChecking for Schema { #[cfg(test)] mod test { use super::*; - use self::edn::NamespacedKeyword; + use self::edn::Keyword; use errors::Error; fn add_attribute(schema: &mut Schema, - ident: NamespacedKeyword, + ident: Keyword, entid: Entid, attribute: Attribute) { @@ -364,7 +364,7 @@ mod test { fn validate_attribute_map_success() { let mut schema = Schema::default(); // attribute that is not an index has no uniqueness - add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 97, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 97, Attribute { index: false, value_type: ValueType::Boolean, fulltext: false, @@ -374,7 +374,7 @@ mod test { no_history: false, }); // attribute is unique by value and an index - add_attribute(&mut schema, NamespacedKeyword::new("foo", "baz"), 98, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "baz"), 98, Attribute { index: true, value_type: ValueType::Long, fulltext: false, @@ -384,7 +384,7 @@ mod test { no_history: false, }); // attribue is unique by identity and an index - add_attribute(&mut schema, NamespacedKeyword::new("foo", "bat"), 99, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "bat"), 99, Attribute { index: true, value_type: ValueType::Ref, fulltext: false, @@ -394,7 +394,7 @@ mod test { no_history: false, }); // attribute is a components and a `Ref` - add_attribute(&mut schema, NamespacedKeyword::new("foo", "bak"), 100, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "bak"), 100, Attribute { index: false, value_type: ValueType::Ref, fulltext: false, @@ -404,7 +404,7 @@ mod test { no_history: false, }); // fulltext attribute is a string and an index - add_attribute(&mut schema, NamespacedKeyword::new("foo", "bap"), 101, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "bap"), 101, Attribute { index: true, value_type: ValueType::String, fulltext: true, @@ -421,7 +421,7 @@ mod test { fn invalid_schema_unique_value_not_index() { let mut schema = Schema::default(); // attribute unique by value but not index - let ident = NamespacedKeyword::new("foo", "bar"); + let ident = Keyword::namespaced("foo", "bar"); add_attribute(&mut schema, ident , 99, Attribute { index: false, value_type: ValueType::Boolean, @@ -445,7 +445,7 @@ mod test { fn invalid_schema_unique_identity_not_index() { let mut schema = Schema::default(); // attribute is unique by identity but not index - add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 99, Attribute { index: false, value_type: ValueType::Long, fulltext: false, @@ -468,7 +468,7 @@ mod test { fn invalid_schema_component_not_ref() { let mut schema = Schema::default(); // attribute that is a component is not a `Ref` - add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 99, Attribute { index: false, value_type: ValueType::Boolean, fulltext: false, @@ -491,7 +491,7 @@ mod test { fn invalid_schema_fulltext_not_index() { let mut schema = Schema::default(); // attribute that is fulltext is not an index - add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 99, Attribute { index: false, value_type: ValueType::String, fulltext: true, @@ -513,7 +513,7 @@ mod test { fn invalid_schema_fulltext_index_not_string() { let mut schema = Schema::default(); // attribute that is fulltext and not a `String` - add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute { + add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 99, Attribute { index: true, value_type: ValueType::Long, fulltext: true, diff --git a/db/src/tx.rs b/db/src/tx.rs index e48f132b..fdb51184 100644 --- a/db/src/tx.rs +++ b/db/src/tx.rs @@ -64,7 +64,7 @@ use db::{ PartitionMapping, }; use edn::{ - NamespacedKeyword, + Keyword, }; use entids; use errors; @@ -165,7 +165,7 @@ pub struct Tx<'conn, 'a, W> where W: TransactWatcher { /// something suitable for the entity position rather than something suitable for a value position. pub fn remove_db_id(map: &mut entmod::MapNotation) -> Result> { // TODO: extract lazy defined constant. - let db_id_key = entmod::Entid::Ident(NamespacedKeyword::new("db", "id")); + let db_id_key = entmod::Entid::Ident(Keyword::namespaced("db", "id")); let db_id: Option = if let Some(id) = map.remove(&db_id_key) { match id { @@ -281,7 +281,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher { } } - fn ensure_ident_exists(&self, e: &NamespacedKeyword) -> Result { + fn ensure_ident_exists(&self, e: &Keyword) -> Result { self.schema.require_entid(e) } diff --git a/db/tests/value_tests.rs b/db/tests/value_tests.rs index 8385260f..4d76af6f 100644 --- a/db/tests/value_tests.rs +++ b/db/tests/value_tests.rs @@ -54,5 +54,5 @@ fn test_to_edn_value_pair() { assert_eq!(TypedValue::Double(OrderedFloat(0.5)).to_edn_value_pair(), (edn::Value::Float(OrderedFloat(0.5)), ValueType::Double)); assert_eq!(TypedValue::typed_string(":db/keyword").to_edn_value_pair(), (edn::Value::Text(":db/keyword".into()), ValueType::String)); - assert_eq!(TypedValue::typed_ns_keyword("db", "keyword").to_edn_value_pair(), (edn::Value::NamespacedKeyword(symbols::NamespacedKeyword::new("db", "keyword")), ValueType::Keyword)); + assert_eq!(TypedValue::typed_ns_keyword("db", "keyword").to_edn_value_pair(), (edn::Value::Keyword(symbols::Keyword::namespaced("db", "keyword")), ValueType::Keyword)); } diff --git a/edn/Cargo.toml b/edn/Cargo.toml index ed824bb8..f8a84597 100644 --- a/edn/Cargo.toml +++ b/edn/Cargo.toml @@ -20,6 +20,10 @@ uuid = { version = "0.5", features = ["v4", "serde"] } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } +[dev-dependencies] +serde_test = "1.0" +serde_json = "1.0" + [features] serde_support = ["serde", "serde_derive"] diff --git a/edn/src/edn.rustpeg b/edn/src/edn.rustpeg index 6c3e2bd7..6689aab6 100644 --- a/edn/src/edn.rustpeg +++ b/edn/src/edn.rustpeg @@ -203,13 +203,13 @@ pub op -> OpType = ":db/add" { OpType::Add } / ":db/retract" { OpType::Retract } -raw_keyword -> NamespacedKeyword - = keyword_prefix ns:$(symbol_namespace) namespace_separator n:$(symbol_name) { NamespacedKeyword::new(ns, n) } +raw_keyword -> Keyword + = keyword_prefix ns:$(symbol_namespace) namespace_separator n:$(symbol_name) { Keyword::namespaced(ns, n) } -raw_forward_keyword -> NamespacedKeyword +raw_forward_keyword -> Keyword = v:raw_keyword {? if v.is_forward() { Ok(v) } else { Err("expected :forward/keyword") } } -raw_backward_keyword -> NamespacedKeyword +raw_backward_keyword -> Keyword = v:raw_keyword {? if v.is_backward() { Ok(v) } else { Err("expected :backward/_keyword") } } entid -> Entid @@ -227,7 +227,7 @@ lookup_ref -> LookupRef = "(" __ "lookup-ref" __ a:(entid) __ v:(value) __ ")" { LookupRef { a, v: v.without_spans() } } tx_function -> TxFunction - = "(" __ n:$(symbol_name) __ ")" { TxFunction { op: PlainSymbol::new(n) } } + = "(" __ n:$(symbol_name) __ ")" { TxFunction { op: PlainSymbol::plain(n) } } entity_place -> EntidOrLookupRefOrTempId = v:raw_text { EntidOrLookupRefOrTempId::TempId(TempId::External(v)) } diff --git a/edn/src/entities.rs b/edn/src/entities.rs index 4eba1912..7d22096d 100644 --- a/edn/src/entities.rs +++ b/edn/src/entities.rs @@ -14,7 +14,7 @@ use std::collections::BTreeMap; use std::fmt; use symbols::{ - NamespacedKeyword, + Keyword, PlainSymbol, }; use types::{ @@ -51,7 +51,7 @@ impl fmt::Display for TempId { #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] pub enum Entid { Entid(i64), - Ident(NamespacedKeyword), + Ident(Keyword), } impl Entid { diff --git a/edn/src/lib.rs b/edn/src/lib.rs index d1e382e2..f8423a37 100644 --- a/edn/src/lib.rs +++ b/edn/src/lib.rs @@ -23,6 +23,8 @@ extern crate serde; extern crate serde_derive; pub mod entities; +// Intentionally not pub. +mod namespaceable_name; pub mod symbols; pub mod types; pub mod pretty_print; @@ -53,7 +55,6 @@ pub use types::{ pub use symbols::{ Keyword, - NamespacedKeyword, NamespacedSymbol, PlainSymbol, }; diff --git a/edn/src/namespaceable_name.rs b/edn/src/namespaceable_name.rs new file mode 100644 index 00000000..562a6b88 --- /dev/null +++ b/edn/src/namespaceable_name.rs @@ -0,0 +1,285 @@ +// Copyright 2018 Mozilla +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +use std::cmp::{ + Ord, + Ordering, + PartialOrd, +}; + +use std::fmt; + +#[cfg(feature = "serde_support")] +use serde::{ + de::{self, Deserialize, Deserializer}, + ser::{Serialize, Serializer} +}; + +// Data storage for both NamespaceableKeyword and NamespaceableSymbol. +#[derive(Clone, Eq, Hash, PartialEq)] +pub struct NamespaceableName { + // The bytes that make up the namespace followed directly by those + // that make up the name. + components: String, + + // The index (in bytes) into `components` where the namespace ends and + // name begins. + // + // If this is zero, it means that this is _not_ a namespaced value! + // + // Important: The following invariants around `boundary` must be maintained + // for memory safety. + // + // 1. `boundary` must always be less than or equal to `components.len()`. + // 2. `boundary` must be byte index that points to a character boundary, + // and not point into the middle of a utf8 codepoint. That is, + // `components.is_char_boundary(boundary)` must always be true. + // + // These invariants are enforced by `NamespaceableName::namespaced()`, and since + // we never mutate `NamespaceableName`s, that's the only place we need to + // worry about them. + boundary: usize, +} + +impl NamespaceableName { + #[inline] + pub fn plain(name: T) -> Self where T: Into { + let n = name.into(); + assert!(!n.is_empty(), "Symbols and keywords cannot be unnamed."); + + NamespaceableName { + components: n, + boundary: 0, + } + } + + #[inline] + pub fn namespaced(namespace: N, name: T) -> Self where N: AsRef, T: AsRef { + let n = name.as_ref(); + let ns = namespace.as_ref(); + + // Note: These invariants are not required for safety. That is, if we + // decide to allow these we can safely remove them. + assert!(!n.is_empty(), "Symbols and keywords cannot be unnamed."); + assert!(!ns.is_empty(), "Symbols and keywords cannot have an empty non-null namespace."); + + let mut dest = String::with_capacity(n.len() + ns.len()); + + dest.push_str(ns); + dest.push_str(n); + + let boundary = ns.len(); + + NamespaceableName { + components: dest, + boundary: boundary, + } + } + + fn dwim(namespace: Option, name: T) -> Self where N: AsRef, T: AsRef { + if let Some(ns) = namespace { + Self::namespaced(ns, name) + } else { + Self::plain(name.as_ref()) + } + } + + pub fn is_namespaced(&self) -> bool { + self.boundary > 0 + } + + #[inline] + pub fn is_backward(&self) -> bool { + self.name().starts_with('_') + } + + #[inline] + pub fn is_forward(&self) -> bool { + !self.is_backward() + } + + pub fn to_reversed(&self) -> NamespaceableName { + let name = self.name(); + + if name.starts_with('_') { + Self::dwim(self.namespace(), &name[1..]) + } else { + Self::dwim(self.namespace(), &format!("_{}", name)) + } + } + + #[inline] + pub fn namespace(&self) -> Option<&str> { + if self.boundary > 0 { + Some(&self.components[0..self.boundary]) + } else { + None + } + } + + #[inline] + pub fn name(&self) -> &str { + if self.boundary == 0 { + &self.components + } else { + &self.components[self.boundary..] + } + } + + #[inline] + pub fn components<'a>(&'a self) -> (&'a str, &'a str) { + self.components.split_at(self.boundary) + } +} + +// We order by namespace then by name. +// Non-namespaced values always sort before. +impl PartialOrd for NamespaceableName { + fn partial_cmp(&self, other: &NamespaceableName) -> Option { + match (self.boundary, other.boundary) { + (0, 0) => self.components.partial_cmp(&other.components), + (0, _) => Some(Ordering::Less), + (_, 0) => Some(Ordering::Greater), + (_, _) => { + // Just use a lexicographic ordering. + self.components().partial_cmp(&other.components()) + }, + } + } +} + +impl Ord for NamespaceableName { + fn cmp(&self, other: &NamespaceableName) -> Ordering { + self.components().cmp(&other.components()) + } +} + +// We could derive this, but it's really hard to make sense of as-is. +impl fmt::Debug for NamespaceableName { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("NamespaceableName") + .field("namespace", &self.namespace()) + .field("name", &self.name()) + .finish() + } +} + +// This is convoluted, but the basic idea is that since we don't want to rely on our input being +// correct, we'll need to implement a custom serializer no matter what (e.g. we can't just +// `derive(Deserialize)` since `unsafe` code depends on `self.boundary` being a valid index). +// +// We'd also like for users consuming our serialized data as e.g. JSON not to have to learn how we +// store NamespaceableName internally, since it's very much an implementation detail. +// +// We achieve both of these by implemeting a type that can serialize in way that's both user- +// friendly and automatic (e.g. `derive`d), and just pass all work off to it in our custom +// implementation of Serialize and Deserialize. +#[cfg(feature = "serde_support")] +#[cfg_attr(feature = "serde_support", serde(rename = "NamespaceableName"))] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +struct SerializedNamespaceableName<'a> { + namespace: Option<&'a str>, + name: &'a str, +} + +#[cfg(feature = "serde_support")] +impl<'de> Deserialize<'de> for NamespaceableName { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + let separated = SerializedNamespaceableName::deserialize(deserializer)?; + if separated.name.len() == 0 { + return Err(de::Error::custom("Empty name in keyword or symbol")); + } + if let Some(ns) = separated.namespace { + if ns.len() == 0 { + Err(de::Error::custom("Empty but present namespace in keyword or symbol")) + } else { + Ok(NamespaceableName::namespaced(ns, separated.name)) + } + } else { + Ok(NamespaceableName::plain(separated.name)) + } + } +} + +#[cfg(feature = "serde_support")] +impl Serialize for NamespaceableName { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + let ser = SerializedNamespaceableName { + namespace: self.namespace(), + name: self.name(), + }; + ser.serialize(serializer) + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::panic; + + #[test] + fn test_new_invariants_maintained() { + assert!(panic::catch_unwind(|| NamespaceableName::namespaced("", "foo")).is_err(), + "Empty namespace should panic"); + assert!(panic::catch_unwind(|| NamespaceableName::namespaced("foo", "")).is_err(), + "Empty name should panic"); + assert!(panic::catch_unwind(|| NamespaceableName::namespaced("", "")).is_err(), + "Should panic if both fields are empty"); + } + + #[test] + fn test_basic() { + let s = NamespaceableName::namespaced("aaaaa", "b"); + assert_eq!(s.namespace(), Some("aaaaa")); + assert_eq!(s.name(), "b"); + assert_eq!(s.components(), ("aaaaa", "b")); + + let s = NamespaceableName::namespaced("b", "aaaaa"); + assert_eq!(s.namespace(), Some("b")); + assert_eq!(s.name(), "aaaaa"); + assert_eq!(s.components(), ("b", "aaaaa")); + } + + #[test] + fn test_order() { + let n0 = NamespaceableName::namespaced("a", "aa"); + let n1 = NamespaceableName::namespaced("aa", "a"); + + let n2 = NamespaceableName::namespaced("a", "ab"); + let n3 = NamespaceableName::namespaced("aa", "b"); + + let n4 = NamespaceableName::namespaced("b", "ab"); + let n5 = NamespaceableName::namespaced("ba", "b"); + + let n6 = NamespaceableName::namespaced("z", "zz"); + + let mut arr = [ + n5.clone(), + n6.clone(), + n0.clone(), + n3.clone(), + n2.clone(), + n1.clone(), + n4.clone() + ]; + + arr.sort(); + + assert_eq!(arr, [ + n0.clone(), + n2.clone(), + n1.clone(), + n3.clone(), + n4.clone(), + n5.clone(), + n6.clone(), + ]); + } +} diff --git a/edn/src/pretty_print.rs b/edn/src/pretty_print.rs index e2669f5d..8c579a48 100644 --- a/edn/src/pretty_print.rs +++ b/edn/src/pretty_print.rs @@ -68,10 +68,9 @@ impl Value { .append(pp.text("}")) .group() } - Value::NamespacedSymbol(ref v) => pp.text(v.namespace.as_ref()).append("/").append(v.name.as_ref()), - Value::PlainSymbol(ref v) => pp.text(v.0.as_ref()), - Value::NamespacedKeyword(ref v) => pp.text(":").append(v.namespace.as_ref()).append("/").append(v.name.as_ref()), - Value::Keyword(ref v) => pp.text(":").append(v.0.as_ref()), + Value::NamespacedSymbol(ref v) => pp.text(v.namespace()).append("/").append(v.name()), + Value::PlainSymbol(ref v) => pp.text(v.to_string()), + Value::Keyword(ref v) => pp.text(v.to_string()), Value::Text(ref v) => pp.text("\"").append(v.as_ref()).append("\""), Value::Uuid(ref u) => pp.text("#uuid \"").append(u.hyphenated().to_string()).append("\""), Value::Instant(ref v) => pp.text("#inst \"").append(v.to_rfc3339_opts(SecondsFormat::AutoSi, true)).append("\""), diff --git a/edn/src/symbols.rs b/edn/src/symbols.rs index 032c4741..9c2c2cb9 100644 --- a/edn/src/symbols.rs +++ b/edn/src/symbols.rs @@ -1,4 +1,4 @@ -// Copyright 2016 Mozilla +// Copyright 2018 Mozilla // // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the @@ -9,11 +9,12 @@ // specific language governing permissions and limitations under the License. use std::fmt::{Display, Formatter}; +use namespaceable_name::NamespaceableName; #[macro_export] macro_rules! ns_keyword { ($ns: expr, $name: expr) => {{ - $crate::NamespacedKeyword::new($ns, $name) + $crate::Keyword::namespaced($ns, $name) }} } @@ -22,12 +23,7 @@ macro_rules! ns_keyword { pub struct PlainSymbol(pub String); #[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)] -pub struct NamespacedSymbol { - // We derive PartialOrd, which implements a lexicographic based - // on the order of members, so put namespace first. - pub namespace: String, - pub name: String, -} +pub struct NamespacedSymbol(NamespaceableName); /// A keyword is a symbol, optionally with a namespace, that prints with a leading colon. /// This concept is imported from Clojure, as it features in EDN and the query @@ -50,12 +46,12 @@ pub struct NamespacedSymbol { /// /// ```rust /// # use edn::symbols::Keyword; -/// # use edn::symbols::NamespacedKeyword; -/// let bar = Keyword::new("bar"); // :bar -/// let foo_bar = NamespacedKeyword::new("foo", "bar"); // :foo/bar -/// assert_eq!("bar", bar.0); -/// assert_eq!("bar", foo_bar.name); -/// assert_eq!("foo", foo_bar.namespace); +/// let bar = Keyword::plain("bar"); // :bar +/// let foo_bar = Keyword::namespaced("foo", "bar"); // :foo/bar +/// assert_eq!("bar", bar.name()); +/// assert_eq!(None, bar.namespace()); +/// assert_eq!("bar", foo_bar.name()); +/// assert_eq!(Some("foo"), foo_bar.namespace()); /// ``` /// /// If you're not sure whether your input is well-formed, you should use a @@ -66,20 +62,12 @@ pub struct NamespacedSymbol { /// /// Future: fast equality (interning?) for keywords. /// -#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)] -pub struct Keyword(pub String); - #[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)] #[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] -pub struct NamespacedKeyword { - // We derive PartialOrd, which implements a lexicographic order based - // on the order of members, so put namespace first. - pub namespace: String, - pub name: String, -} +pub struct Keyword(NamespaceableName); impl PlainSymbol { - pub fn new(name: T) -> Self where T: Into { + pub fn plain(name: T) -> Self where T: Into { let n = name.into(); assert!(!n.is_empty(), "Symbols cannot be unnamed."); @@ -90,11 +78,11 @@ impl PlainSymbol { /// /// ```rust /// # use edn::symbols::PlainSymbol; - /// assert_eq!("foo", PlainSymbol::new("?foo").plain_name()); - /// assert_eq!("foo", PlainSymbol::new("$foo").plain_name()); - /// assert_eq!("!foo", PlainSymbol::new("!foo").plain_name()); + /// assert_eq!("foo", PlainSymbol::plain("?foo").name()); + /// assert_eq!("foo", PlainSymbol::plain("$foo").name()); + /// assert_eq!("!foo", PlainSymbol::plain("!foo").name()); /// ``` - pub fn plain_name(&self) -> &str { + pub fn name(&self) -> &str { if self.is_src_symbol() || self.is_var_symbol() { &self.0[1..] } else { @@ -114,52 +102,68 @@ impl PlainSymbol { } impl NamespacedSymbol { - pub fn new(namespace: T, name: T) -> Self where T: Into { - let n = name.into(); - let ns = namespace.into(); + pub fn namespaced(namespace: N, name: T) -> Self where N: AsRef, T: AsRef { + let r = namespace.as_ref(); + assert!(!r.is_empty(), "Namespaced symbols cannot have an empty non-null namespace."); + NamespacedSymbol(NamespaceableName::namespaced(r, name)) + } - assert!(!n.is_empty(), "Symbols cannot be unnamed."); - assert!(!ns.is_empty(), "Symbols cannot have an empty non-null namespace."); + #[inline] + pub fn name(&self) -> &str { + self.0.name() + } - NamespacedSymbol { name: n, namespace: ns } + #[inline] + pub fn namespace(&self) -> &str { + self.0.namespace().unwrap() + } + + #[inline] + pub fn components<'a>(&'a self) -> (&'a str, &'a str) { + self.0.components() } } impl Keyword { - pub fn new(name: T) -> Self where T: Into { - let n = name.into(); - assert!(!n.is_empty(), "Keywords cannot be unnamed."); - - Keyword(n) + pub fn plain(name: T) -> Self where T: Into { + Keyword(NamespaceableName::plain(name)) } } -impl NamespacedKeyword { - /// Creates a new `NamespacedKeyword`. +impl Keyword { + /// Creates a new `Keyword`. /// /// # Examples /// /// ```rust - /// # use edn::symbols::NamespacedKeyword; - /// let keyword = NamespacedKeyword::new("foo", "bar"); + /// # use edn::symbols::Keyword; + /// let keyword = Keyword::namespaced("foo", "bar"); /// assert_eq!(keyword.to_string(), ":foo/bar"); /// ``` /// /// See also the `kw!` macro in the main `mentat` crate. - pub fn new(namespace: T, name: T) -> Self where T: Into { - let n = name.into(); - let ns = namespace.into(); - assert!(!n.is_empty(), "Keywords cannot be unnamed."); - assert!(!ns.is_empty(), "Keywords cannot have an empty non-null namespace."); - - // TODO: debug asserts to ensure that neither field matches [ :/]. - NamespacedKeyword { - name: n, - namespace: ns, - } + pub fn namespaced(namespace: N, name: T) -> Self where N: AsRef, T: AsRef { + let r = namespace.as_ref(); + assert!(!r.is_empty(), "Namespaced keywords cannot have an empty non-null namespace."); + Keyword(NamespaceableName::namespaced(r, name)) } - /// Whether this `NamespacedKeyword` should be interpreted in reverse order. For example, + #[inline] + pub fn name(&self) -> &str { + self.0.name() + } + + #[inline] + pub fn namespace(&self) -> Option<&str> { + self.0.namespace() + } + + #[inline] + pub fn components<'a>(&'a self) -> (&'a str, &'a str) { + self.0.components() + } + + /// Whether this `Keyword` should be interpreted in reverse order. For example, /// the two following snippets are identical: /// /// ```edn @@ -173,38 +177,46 @@ impl NamespacedKeyword { /// # Examples /// /// ```rust - /// # use edn::symbols::NamespacedKeyword; - /// assert!(!NamespacedKeyword::new("foo", "bar").is_backward()); - /// assert!(NamespacedKeyword::new("foo", "_bar").is_backward()); + /// # use edn::symbols::Keyword; + /// assert!(!Keyword::namespaced("foo", "bar").is_backward()); + /// assert!(Keyword::namespaced("foo", "_bar").is_backward()); /// ``` #[inline] pub fn is_backward(&self) -> bool { - self.name.starts_with('_') + self.0.is_backward() } - /// Whether this `NamespacedKeyword` should be interpreted in forward order. - /// See `symbols::NamespacedKeyword::is_backward`. + /// Whether this `Keyword` should be interpreted in forward order. + /// See `symbols::Keyword::is_backward`. /// /// # Examples /// /// ```rust - /// # use edn::symbols::NamespacedKeyword; - /// assert!(NamespacedKeyword::new("foo", "bar").is_forward()); - /// assert!(!NamespacedKeyword::new("foo", "_bar").is_forward()); + /// # use edn::symbols::Keyword; + /// assert!(Keyword::namespaced("foo", "bar").is_forward()); + /// assert!(!Keyword::namespaced("foo", "_bar").is_forward()); /// ``` #[inline] pub fn is_forward(&self) -> bool { - !self.is_backward() + self.0.is_forward() } - /// Returns a `NamespacedKeyword` with the same namespace and a - /// 'backward' name. See `symbols::NamespacedKeyword::is_backward`. + #[inline] + pub fn is_namespaced(&self) -> bool { + self.0.is_namespaced() + } + + /// Returns a `Keyword` with the same namespace and a + /// 'backward' name. See `symbols::Keyword::is_backward`. + /// + /// Returns a forward name if passed a reversed keyword; i.e., this + /// function is its own inverse. /// /// # Examples /// /// ```rust - /// # use edn::symbols::NamespacedKeyword; - /// let nsk = NamespacedKeyword::new("foo", "bar"); + /// # use edn::symbols::Keyword; + /// let nsk = Keyword::namespaced("foo", "bar"); /// assert!(!nsk.is_backward()); /// assert_eq!(":foo/bar", nsk.to_string()); /// @@ -212,38 +224,26 @@ impl NamespacedKeyword { /// assert!(reversed.is_backward()); /// assert_eq!(":foo/_bar", reversed.to_string()); /// ``` - pub fn to_reversed(&self) -> NamespacedKeyword { - let name = if self.is_backward() { - self.name[1..].to_string() - } else { - format!("{}{}", "_", self.name) - }; - - NamespacedKeyword { - name: name, - namespace: self.namespace.clone(), - } + pub fn to_reversed(&self) -> Keyword { + Keyword(self.0.to_reversed()) } - /// If this `NamespacedKeyword` is 'backward' (see `symbols::NamespacedKeyword::is_backward`), + /// If this `Keyword` is 'backward' (see `symbols::Keyword::is_backward`), /// return `Some('forward name')`; otherwise, return `None`. /// /// # Examples /// /// ```rust - /// # use edn::symbols::NamespacedKeyword; - /// let nsk = NamespacedKeyword::new("foo", "bar"); + /// # use edn::symbols::Keyword; + /// let nsk = Keyword::namespaced("foo", "bar"); /// assert_eq!(None, nsk.unreversed()); /// /// let reversed = nsk.to_reversed(); /// assert_eq!(Some(nsk), reversed.unreversed()); /// ``` - pub fn unreversed(&self) -> Option { + pub fn unreversed(&self) -> Option { if self.is_backward() { - Some(NamespacedKeyword { - name: self.name[1..].to_string(), - namespace: self.namespace.clone(), - }) + Some(self.to_reversed()) } else { None } @@ -261,7 +261,7 @@ impl Display for PlainSymbol { /// /// ```rust /// # use edn::symbols::PlainSymbol; - /// assert_eq!("baz", PlainSymbol::new("baz").to_string()); + /// assert_eq!("baz", PlainSymbol::plain("baz").to_string()); /// ``` fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result { write!(f, "{}", self.0) @@ -275,10 +275,10 @@ impl Display for NamespacedSymbol { /// /// ```rust /// # use edn::symbols::NamespacedSymbol; - /// assert_eq!("bar/baz", NamespacedSymbol::new("bar", "baz").to_string()); + /// assert_eq!("bar/baz", NamespacedSymbol::namespaced("bar", "baz").to_string()); /// ``` fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result { - write!(f, "{}/{}", self.namespace, self.name) + write!(f, "{}/{}", self.namespace(), self.name()) } } @@ -289,33 +289,25 @@ impl Display for Keyword { /// /// ```rust /// # use edn::symbols::Keyword; - /// assert_eq!(":baz", Keyword::new("baz").to_string()); + /// assert_eq!(":baz", Keyword::plain("baz").to_string()); + /// assert_eq!(":bar/baz", Keyword::namespaced("bar", "baz").to_string()); + /// assert_eq!(":bar/_baz", Keyword::namespaced("bar", "baz").to_reversed().to_string()); + /// assert_eq!(":bar/baz", Keyword::namespaced("bar", "baz").to_reversed().to_reversed().to_string()); /// ``` fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result { - write!(f, ":{}", self.0) - } -} - -impl Display for NamespacedKeyword { - /// Print the keyword in EDN format. - /// - /// # Examples - /// - /// ```rust - /// # use edn::symbols::NamespacedKeyword; - /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_string()); - /// assert_eq!(":bar/_baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_string()); - /// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_reversed().to_string()); - /// ``` - fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result { - write!(f, ":{}/{}", self.namespace, self.name) + if self.0.is_namespaced() { + let (ns, name) = self.0.components(); + write!(f, ":{}/{}", ns, name) + } else { + write!(f, ":{}", self.0.name()) + } } } #[test] fn test_ns_keyword_macro() { assert_eq!(ns_keyword!("test", "name").to_string(), - NamespacedKeyword::new("test", "name").to_string()); + Keyword::namespaced("test", "name").to_string()); assert_eq!(ns_keyword!("ns", "_name").to_string(), - NamespacedKeyword::new("ns", "_name").to_string()); + Keyword::namespaced("ns", "_name").to_string()); } diff --git a/edn/src/types.rs b/edn/src/types.rs index f930afcf..ada7929b 100644 --- a/edn/src/types.rs +++ b/edn/src/types.rs @@ -41,7 +41,6 @@ pub enum Value { PlainSymbol(symbols::PlainSymbol), NamespacedSymbol(symbols::NamespacedSymbol), Keyword(symbols::Keyword), - NamespacedKeyword(symbols::NamespacedKeyword), Vector(Vec), // We're using a LinkedList here instead of a Vec or VecDeque because the // LinkedList is faster for appending (which we do a lot of). @@ -70,7 +69,6 @@ pub enum SpannedValue { PlainSymbol(symbols::PlainSymbol), NamespacedSymbol(symbols::NamespacedSymbol), Keyword(symbols::Keyword), - NamespacedKeyword(symbols::NamespacedKeyword), Vector(Vec), List(LinkedList), Set(BTreeSet), @@ -159,7 +157,6 @@ impl From for Value { SpannedValue::PlainSymbol(v) => Value::PlainSymbol(v), SpannedValue::NamespacedSymbol(v) => Value::NamespacedSymbol(v), SpannedValue::Keyword(v) => Value::Keyword(v), - SpannedValue::NamespacedKeyword(v) => Value::NamespacedKeyword(v), SpannedValue::Vector(v) => Value::Vector(v.into_iter().map(|x| x.without_spans()).collect()), SpannedValue::List(v) => Value::List(v.into_iter().map(|x| x.without_spans()).collect()), SpannedValue::Set(v) => Value::Set(v.into_iter().map(|x| x.without_spans()).collect()), @@ -249,10 +246,10 @@ macro_rules! def_into { /// # use edn::types::Value; /// # use edn::symbols; /// let value = to_symbol!("foo", "bar", Value); -/// assert_eq!(value, Value::NamespacedSymbol(symbols::NamespacedSymbol::new("foo", "bar"))); +/// assert_eq!(value, Value::NamespacedSymbol(symbols::NamespacedSymbol::namespaced("foo", "bar"))); /// /// let value = to_symbol!(None, "baz", Value); -/// assert_eq!(value, Value::PlainSymbol(symbols::PlainSymbol::new("baz"))); +/// assert_eq!(value, Value::PlainSymbol(symbols::PlainSymbol::plain("baz"))); /// /// let value = to_symbol!("foo", "bar", SpannedValue); /// assert_eq!(value.into(), to_symbol!("foo", "bar", Value)); @@ -263,8 +260,8 @@ macro_rules! def_into { macro_rules! to_symbol { ( $namespace:expr, $name:expr, $t:tt ) => { $namespace.into().map_or_else( - || $t::PlainSymbol(symbols::PlainSymbol::new($name)), - |ns| $t::NamespacedSymbol(symbols::NamespacedSymbol::new(ns, $name))) + || $t::PlainSymbol(symbols::PlainSymbol::plain($name)), + |ns| $t::NamespacedSymbol(symbols::NamespacedSymbol::namespaced(ns, $name))) } } @@ -278,10 +275,10 @@ macro_rules! to_symbol { /// # use edn::types::Value; /// # use edn::symbols; /// let value = to_keyword!("foo", "bar", Value); -/// assert_eq!(value, Value::NamespacedKeyword(symbols::NamespacedKeyword::new("foo", "bar"))); +/// assert_eq!(value, Value::Keyword(symbols::Keyword::namespaced("foo", "bar"))); /// /// let value = to_keyword!(None, "baz", Value); -/// assert_eq!(value, Value::Keyword(symbols::Keyword::new("baz"))); +/// assert_eq!(value, Value::Keyword(symbols::Keyword::plain("baz"))); /// /// let value = to_keyword!("foo", "bar", SpannedValue); /// assert_eq!(value.into(), to_keyword!("foo", "bar", Value)); @@ -292,8 +289,8 @@ macro_rules! to_symbol { macro_rules! to_keyword { ( $namespace:expr, $name:expr, $t:tt ) => { $namespace.into().map_or_else( - || $t::Keyword(symbols::Keyword::new($name)), - |ns| $t::NamespacedKeyword(symbols::NamespacedKeyword::new(ns, $name))) + || $t::Keyword(symbols::Keyword::plain($name)), + |ns| $t::Keyword(symbols::Keyword::namespaced(ns, $name))) } } @@ -311,13 +308,25 @@ macro_rules! def_common_value_methods { def_is!(is_uuid, $t::Uuid(_)); def_is!(is_symbol, $t::PlainSymbol(_)); def_is!(is_namespaced_symbol, $t::NamespacedSymbol(_)); - def_is!(is_keyword, $t::Keyword(_)); - def_is!(is_namespaced_keyword, $t::NamespacedKeyword(_)); def_is!(is_vector, $t::Vector(_)); def_is!(is_list, $t::List(_)); def_is!(is_set, $t::Set(_)); def_is!(is_map, $t::Map(_)); + pub fn is_keyword(&self) -> bool { + match self { + &$t::Keyword(ref k) => !k.is_namespaced(), + _ => false, + } + } + + pub fn is_namespaced_keyword(&self) -> bool { + match self { + &$t::Keyword(ref k) => k.is_namespaced(), + _ => false, + } + } + /// `as_nil` does not use the macro as it does not have an underlying /// value, and returns `Option<()>`. pub fn as_nil(&self) -> Option<()> { @@ -335,8 +344,21 @@ macro_rules! def_common_value_methods { def_as_ref!(as_uuid, $t::Uuid, Uuid); def_as_ref!(as_symbol, $t::PlainSymbol, symbols::PlainSymbol); def_as_ref!(as_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol); - def_as_ref!(as_keyword, $t::Keyword, symbols::Keyword); - def_as_ref!(as_namespaced_keyword, $t::NamespacedKeyword, symbols::NamespacedKeyword); + + pub fn as_keyword(&self) -> Option<&symbols::Keyword> { + match self { + &$t::Keyword(ref k) if !k.is_namespaced() => Some(k), + _ => None, + } + } + + pub fn as_namespaced_keyword(&self) -> Option<&symbols::Keyword> { + match self { + &$t::Keyword(ref k) if k.is_namespaced() => Some(k), + _ => None, + } + } + def_as_ref!(as_vector, $t::Vector, Vec<$tchild>); def_as_ref!(as_list, $t::List, LinkedList<$tchild>); def_as_ref!(as_set, $t::Set, BTreeSet<$tchild>); @@ -352,8 +374,34 @@ macro_rules! def_common_value_methods { def_into!(into_uuid, $t::Uuid, Uuid,); def_into!(into_symbol, $t::PlainSymbol, symbols::PlainSymbol,); def_into!(into_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol,); - def_into!(into_keyword, $t::Keyword, symbols::Keyword,); - def_into!(into_namespaced_keyword, $t::NamespacedKeyword, symbols::NamespacedKeyword,); + + pub fn into_keyword(self) -> Option { + match self { + $t::Keyword(k) => { + if !k.is_namespaced() { + Some(k) + } else { + None + } + }, + _ => None, + } + } + + pub fn into_namespaced_keyword(self) -> Option { + match self { + $t::Keyword(k) => { + if k.is_namespaced() { + Some(k) + } else { + None + } + }, + _ => None, + } + } + + def_into!(into_vector, $t::Vector, Vec<$tchild>,); def_into!(into_list, $t::List, LinkedList<$tchild>,); def_into!(into_set, $t::Set, BTreeSet<$tchild>,); @@ -383,8 +431,8 @@ macro_rules! def_common_value_methods { $t::Uuid(_) => 7, $t::PlainSymbol(_) => 8, $t::NamespacedSymbol(_) => 9, - $t::Keyword(_) => 10, - $t::NamespacedKeyword(_) => 11, + $t::Keyword(ref k) if !k.is_namespaced() => 10, + $t::Keyword(_) => 11, $t::Vector(_) => 12, $t::List(_) => 13, $t::Set(_) => 14, @@ -405,7 +453,6 @@ macro_rules! def_common_value_methods { $t::PlainSymbol(_) => false, $t::NamespacedSymbol(_) => false, $t::Keyword(_) => false, - $t::NamespacedKeyword(_) => false, $t::Vector(_) => true, $t::List(_) => true, $t::Set(_) => true, @@ -443,7 +490,6 @@ macro_rules! def_common_value_ord { (&$t::PlainSymbol(ref a), &$t::PlainSymbol(ref b)) => b.cmp(a), (&$t::NamespacedSymbol(ref a), &$t::NamespacedSymbol(ref b)) => b.cmp(a), (&$t::Keyword(ref a), &$t::Keyword(ref b)) => b.cmp(a), - (&$t::NamespacedKeyword(ref a), &$t::NamespacedKeyword(ref b)) => b.cmp(a), (&$t::Vector(ref a), &$t::Vector(ref b)) => b.cmp(a), (&$t::List(ref a), &$t::List(ref b)) => b.cmp(a), (&$t::Set(ref a), &$t::Set(ref b)) => b.cmp(a), @@ -482,7 +528,6 @@ macro_rules! def_common_value_display { $t::PlainSymbol(ref v) => v.fmt($f), $t::NamespacedSymbol(ref v) => v.fmt($f), $t::Keyword(ref v) => v.fmt($f), - $t::NamespacedKeyword(ref v) => v.fmt($f), $t::Vector(ref v) => { write!($f, "[")?; for x in v { diff --git a/edn/tests/serde_support.rs b/edn/tests/serde_support.rs new file mode 100644 index 00000000..7a460b52 --- /dev/null +++ b/edn/tests/serde_support.rs @@ -0,0 +1,56 @@ +// Copyright 2018 Mozilla +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + + +#![cfg(feature = "serde_support")] + +extern crate serde_test; +extern crate serde_json; + +extern crate edn; +use edn::symbols::Keyword; +use serde_test::{assert_tokens, Token}; + +#[cfg(feature = "serde_support")] +#[test] +fn test_serialize_keyword() { + let kw = Keyword::namespaced("foo", "bar"); + assert_tokens(&kw, &[ + Token::NewtypeStruct { name: "Keyword" }, + Token::Struct { name: "NamespaceableName", len: 2 }, + Token::Str("namespace"), + Token::Some, + Token::BorrowedStr("foo"), + Token::Str("name"), + Token::BorrowedStr("bar"), + Token::StructEnd, + ]); +} + + +#[cfg(feature = "serde_support")] +#[test] +fn test_deserialize_keyword() { + let json = r#"{"name": "foo", "namespace": "bar"}"#; + let kw = serde_json::from_str::(json).unwrap(); + assert_eq!(kw.name(), "foo"); + assert_eq!(kw.namespace(), Some("bar")); + + let bad_ns_json = r#"{"name": "foo", "namespace": ""}"#; + let not_kw = serde_json::from_str::(bad_ns_json); + assert!(not_kw.is_err()); + + let bad_ns_json = r#"{"name": "", "namespace": "bar"}"#; + let not_kw = serde_json::from_str::(bad_ns_json); + assert!(not_kw.is_err()); +} + + + diff --git a/edn/tests/tests.rs b/edn/tests/tests.rs index c1a8e74b..37d2013d 100644 --- a/edn/tests/tests.rs +++ b/edn/tests/tests.rs @@ -38,22 +38,22 @@ use edn::utils; // Helper for making wrapped keywords with a namespace. fn k_ns(ns: &str, name: &str) -> Value { - Value::NamespacedKeyword(symbols::NamespacedKeyword::new(ns, name)) + Value::Keyword(symbols::Keyword::namespaced(ns, name)) } // Helper for making wrapped keywords without a namespace. fn k_plain(name: &str) -> Value { - Value::Keyword(symbols::Keyword::new(name)) + Value::Keyword(symbols::Keyword::plain(name)) } // Helper for making wrapped symbols with a namespace fn s_ns(ns: &str, name: &str) -> Value { - Value::NamespacedSymbol(symbols::NamespacedSymbol::new(ns, name)) + Value::NamespacedSymbol(symbols::NamespacedSymbol::namespaced(ns, name)) } // Helper for making wrapped symbols without a namespace fn s_plain(name: &str) -> Value { - Value::PlainSymbol(symbols::PlainSymbol::new(name)) + Value::PlainSymbol(symbols::PlainSymbol::plain(name)) } // Helpers for parsing strings and converting them into edn::Value. @@ -831,7 +831,7 @@ fn test_map() { let test = "{:a 1, $b {:b/a nil, :b/b #{nil 5}}, c [1 2], d (3 4)}"; let value = Map(BTreeMap::from_iter(vec![ - (Keyword(symbols::Keyword::new("a")), Integer(1)), + (Keyword(symbols::Keyword::plain("a")), Integer(1)), (s_plain("$b"), Map(BTreeMap::from_iter(vec![ (k_ns("b", "a"), Nil), (k_ns("b", "b"), Set(BTreeSet::from_iter(vec![ @@ -1457,7 +1457,7 @@ fn test_is_and_as_type_helper_functions() { assert_eq!(values.len(), is_result.len()); for (j, result) in is_result.iter().enumerate() { - assert_eq!(j == i, *result); + assert_eq!(j == i, *result, "Expected {} = {} to equal {}", j, i, result); } if i == 0 { @@ -1474,10 +1474,10 @@ fn test_is_and_as_type_helper_functions() { def_test_as_type!(value, as_big_integer, i == 3, &max_i64 * &max_i64); def_test_as_type!(value, as_ordered_float, i == 4, OrderedFloat(22.22f64)); def_test_as_type!(value, as_text, i == 5, "hello world".to_string()); - def_test_as_type!(value, as_symbol, i == 6, symbols::PlainSymbol::new("$symbol")); - def_test_as_type!(value, as_namespaced_symbol, i == 7, symbols::NamespacedSymbol::new("$ns", "$symbol")); - def_test_as_type!(value, as_keyword, i == 8, symbols::Keyword::new("hello")); - def_test_as_type!(value, as_namespaced_keyword, i == 9, symbols::NamespacedKeyword::new("hello", "world")); + def_test_as_type!(value, as_symbol, i == 6, symbols::PlainSymbol::plain("$symbol")); + def_test_as_type!(value, as_namespaced_symbol, i == 7, symbols::NamespacedSymbol::namespaced("$ns", "$symbol")); + def_test_as_type!(value, as_keyword, i == 8, symbols::Keyword::plain("hello")); + def_test_as_type!(value, as_namespaced_keyword, i == 9, symbols::Keyword::namespaced("hello", "world")); def_test_as_type!(value, as_vector, i == 10, vec![Value::Integer(1)]); def_test_as_type!(value, as_list, i == 11, LinkedList::from_iter(vec![])); def_test_as_type!(value, as_set, i == 12, BTreeSet::from_iter(vec![])); @@ -1492,10 +1492,10 @@ fn test_is_and_as_type_helper_functions() { def_test_into_type!(value, into_big_integer, i == 3, &max_i64 * &max_i64); def_test_into_type!(value, into_ordered_float, i == 4, OrderedFloat(22.22f64)); def_test_into_type!(value, into_text, i == 5, "hello world".to_string()); - def_test_into_type!(value, into_symbol, i == 6, symbols::PlainSymbol::new("$symbol")); - def_test_into_type!(value, into_namespaced_symbol, i == 7, symbols::NamespacedSymbol::new("$ns", "$symbol")); - def_test_into_type!(value, into_keyword, i == 8, symbols::Keyword::new("hello")); - def_test_into_type!(value, into_namespaced_keyword, i == 9, symbols::NamespacedKeyword::new("hello", "world")); + def_test_into_type!(value, into_symbol, i == 6, symbols::PlainSymbol::plain("$symbol")); + def_test_into_type!(value, into_namespaced_symbol, i == 7, symbols::NamespacedSymbol::namespaced("$ns", "$symbol")); + def_test_into_type!(value, into_keyword, i == 8, symbols::Keyword::plain("hello")); + def_test_into_type!(value, into_namespaced_keyword, i == 9, symbols::Keyword::namespaced("hello", "world")); def_test_into_type!(value, into_vector, i == 10, vec![Value::Integer(1)]); def_test_into_type!(value, into_list, i == 11, LinkedList::from_iter(vec![])); def_test_into_type!(value, into_set, i == 12, BTreeSet::from_iter(vec![])); diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index 50ab0096..b657e871 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -32,7 +32,7 @@ pub use mentat::{ FindSpec, HasSchema, KnownEntid, - NamespacedKeyword, + Keyword, Queryable, QueryBuilder, QueryInputs, diff --git a/ffi/src/utils.rs b/ffi/src/utils.rs index 42e812ce..76aeee47 100644 --- a/ffi/src/utils.rs +++ b/ffi/src/utils.rs @@ -16,7 +16,7 @@ pub mod strings { use std::os::raw::c_char; use mentat::{ - NamespacedKeyword, + Keyword, }; pub fn c_char_to_string(cchar: *const c_char) -> String { @@ -30,10 +30,10 @@ pub mod strings { } // TODO: validate. The input might not be a keyword! - pub fn kw_from_string(mut keyword_string: String) -> NamespacedKeyword { + pub fn kw_from_string(mut keyword_string: String) -> Keyword { let attr_name = keyword_string.split_off(1); let parts: Vec<&str> = attr_name.split("/").collect(); - NamespacedKeyword::new(parts[0], parts[1]) + Keyword::namespaced(parts[0], parts[1]) } } diff --git a/parser-utils/src/macros.rs b/parser-utils/src/macros.rs index 98888a73..d6a3d0a2 100644 --- a/parser-utils/src/macros.rs +++ b/parser-utils/src/macros.rs @@ -58,7 +58,7 @@ macro_rules! matches_plain_symbol { ($name: expr, $input: ident) => { satisfy_map(|x: edn::Value| { if let edn::Value::PlainSymbol(ref s) = x { - if s.0.as_str() == $name { + if s.name() == $name { return Some(()); } } diff --git a/parser-utils/src/value_and_span.rs b/parser-utils/src/value_and_span.rs index ba073ad7..82483055 100644 --- a/parser-utils/src/value_and_span.rs +++ b/parser-utils/src/value_and_span.rs @@ -442,34 +442,37 @@ pub fn integer<'a>() -> Expected, fn(Stream<'a>) -> ParseRes parser(integer_ as fn(Stream<'a>) -> ParseResult>).expected("integer") } -pub fn namespaced_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>> { - satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword()) +pub fn namespaced_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>> { + satisfy_map(|v: &'a edn::ValueAndSpan| + v.inner.as_namespaced_keyword() + .and_then(|k| if k.is_namespaced() { Some(k) } else { None }) + ) .parse_lazy(input) .into() } -pub fn namespaced_keyword<'a>() -> Expected, fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>>> { - parser(namespaced_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>).expected("namespaced_keyword") +pub fn namespaced_keyword<'a>() -> Expected, fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>>> { + parser(namespaced_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>).expected("namespaced_keyword") } -pub fn forward_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>> { - satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword().and_then(|k| if k.is_forward() { Some(k) } else { None })) +pub fn forward_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>> { + satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword().and_then(|k| if k.is_forward() && k.is_namespaced() { Some(k) } else { None })) .parse_lazy(input) .into() } -pub fn forward_keyword<'a>() -> Expected, fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>>> { - parser(forward_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>).expected("forward_keyword") +pub fn forward_keyword<'a>() -> Expected, fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>>> { + parser(forward_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>).expected("forward_keyword") } -pub fn backward_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>> { - satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword().and_then(|k| if k.is_backward() { Some(k) } else { None })) +pub fn backward_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>> { + satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword().and_then(|k| if k.is_backward() && k.is_namespaced() { Some(k) } else { None })) .parse_lazy(input) .into() } -pub fn backward_keyword<'a>() -> Expected, fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>>> { - parser(backward_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>).expected("backward_keyword") +pub fn backward_keyword<'a>() -> Expected, fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>>> { + parser(backward_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>).expected("backward_keyword") } /// Generate a `satisfy` expression that matches a `PlainSymbol` value with the given name. @@ -482,7 +485,7 @@ macro_rules! def_matches_plain_symbol { def_parser!($parser, $name, &'a edn::ValueAndSpan, { satisfy(|v: &'a edn::ValueAndSpan| { match v.inner { - edn::SpannedValue::PlainSymbol(ref s) => s.0.as_str() == $input, + edn::SpannedValue::PlainSymbol(ref s) => s.name() == $input, _ => false, } }) @@ -499,7 +502,7 @@ macro_rules! def_matches_keyword { def_parser!($parser, $name, &'a edn::ValueAndSpan, { satisfy(|v: &'a edn::ValueAndSpan| { match v.inner { - edn::SpannedValue::Keyword(ref s) => s.0.as_str() == $input, + edn::SpannedValue::Keyword(ref s) if !s.is_namespaced() => s.name() == $input, _ => false, } }) @@ -507,7 +510,7 @@ macro_rules! def_matches_keyword { } } -/// Generate a `satisfy` expression that matches a `NamespacedKeyword` value with the given +/// Generate a `satisfy` expression that matches a `Keyword` value with the given /// namespace and name. /// /// We do this rather than using `combine::token` to save allocations. @@ -517,7 +520,10 @@ macro_rules! def_matches_namespaced_keyword { def_parser!($parser, $name, &'a edn::ValueAndSpan, { satisfy(|v: &'a edn::ValueAndSpan| { match v.inner { - edn::SpannedValue::NamespacedKeyword(ref s) => s.namespace.as_str() == $input_namespace && s.name.as_str() == $input_name, + edn::SpannedValue::Keyword(ref s) if s.is_namespaced() => { + let (ns, n) = s.components(); + ns == $input_namespace && n == $input_name + }, _ => false, } }) @@ -565,7 +571,7 @@ macro_rules! keyword_map_parser { Ok(value) => { $( if let Some(ref keyword) = value.inner.as_keyword() { - if keyword.0.as_str() == *$keyword { + if &keyword.name() == $keyword { if $tmp.is_some() { // Repeated match -- bail out! Providing good error // messages is hard; this will do for now. @@ -711,7 +717,7 @@ mod tests { fn test_keyword_map_failures() { assert_parse_failure_contains!(|| vector().of_exactly(keyword_map_of!(("x", Test::entid()), ("y", Test::entid()))), "[:x 1 :x 2]", - r#"errors: [Unexpected(Token(ValueAndSpan { inner: Keyword(Keyword("x"))"#); + r#"errors: [Unexpected(Token(ValueAndSpan { inner: Keyword(Keyword(NamespaceableName { namespace: None, name: "x" }))"#); } diff --git a/query-algebrizer/src/clauses/fulltext.rs b/query-algebrizer/src/clauses/fulltext.rs index 53121bc3..1fbae1f2 100644 --- a/query-algebrizer/src/clauses/fulltext.rs +++ b/query-algebrizer/src/clauses/fulltext.rs @@ -269,7 +269,7 @@ mod testing { use mentat_query::{ Binding, FnArg, - NamespacedKeyword, + Keyword, PlainSymbol, Variable, }; @@ -284,14 +284,14 @@ mod testing { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 101); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 101); add_attribute(&mut schema, 101, Attribute { value_type: ValueType::String, fulltext: false, ..Default::default() }); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "fts"), 100); + associate_ident(&mut schema, Keyword::namespaced("foo", "fts"), 100); add_attribute(&mut schema, 100, Attribute { value_type: ValueType::String, index: true, @@ -301,12 +301,12 @@ mod testing { let known = Known::for_schema(&schema); - let op = PlainSymbol::new("fulltext"); + let op = PlainSymbol::plain("fulltext"); cc.apply_fulltext(known, WhereFn { operator: op, args: vec![ FnArg::SrcVar(SrcVar::DefaultSrc), - FnArg::IdentOrKeyword(NamespacedKeyword::new("foo", "fts")), + FnArg::IdentOrKeyword(Keyword::namespaced("foo", "fts")), FnArg::Constant("needle".into()), ], binding: Binding::BindRel(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?entity")), @@ -359,12 +359,12 @@ mod testing { vec![ValueType::Double].into_iter().collect()); let mut cc = ConjoiningClauses::default(); - let op = PlainSymbol::new("fulltext"); + let op = PlainSymbol::plain("fulltext"); cc.apply_fulltext(known, WhereFn { operator: op, args: vec![ FnArg::SrcVar(SrcVar::DefaultSrc), - FnArg::IdentOrKeyword(NamespacedKeyword::new("foo", "bar")), + FnArg::IdentOrKeyword(Keyword::namespaced("foo", "bar")), FnArg::Constant("needle".into()), ], binding: Binding::BindRel(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?entity")), diff --git a/query-algebrizer/src/clauses/ground.rs b/query-algebrizer/src/clauses/ground.rs index 5d638485..cedb2e2a 100644 --- a/query-algebrizer/src/clauses/ground.rs +++ b/query-algebrizer/src/clauses/ground.rs @@ -329,7 +329,7 @@ mod testing { use mentat_query::{ Binding, FnArg, - NamespacedKeyword, + Keyword, PlainSymbol, Variable, }; @@ -346,7 +346,7 @@ mod testing { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "fts"), 100); + associate_ident(&mut schema, Keyword::namespaced("foo", "fts"), 100); add_attribute(&mut schema, 100, Attribute { value_type: ValueType::String, index: true, @@ -358,7 +358,7 @@ mod testing { // It's awkward enough to write these expansions that we give the details for the simplest // case only. See the tests of the translator for more extensive (albeit looser) coverage. - let op = PlainSymbol::new("ground"); + let op = PlainSymbol::plain("ground"); cc.apply_ground(known, WhereFn { operator: op, args: vec![ diff --git a/query-algebrizer/src/clauses/mod.rs b/query-algebrizer/src/clauses/mod.rs index 7009b505..603c6dae 100644 --- a/query-algebrizer/src/clauses/mod.rs +++ b/query-algebrizer/src/clauses/mod.rs @@ -42,7 +42,7 @@ use mentat_core::counter::RcCounter; use mentat_query::{ Element, FindSpec, - NamespacedKeyword, + Keyword, Pull, Variable, WhereClause, @@ -760,7 +760,7 @@ impl ConjoiningClauses { self.empty_because = Some(why); } - fn entid_for_ident<'s, 'a>(&self, schema: &'s Schema, ident: &'a NamespacedKeyword) -> Option { + fn entid_for_ident<'s, 'a>(&self, schema: &'s Schema, ident: &'a Keyword) -> Option { schema.get_entid(&ident) } @@ -1155,7 +1155,7 @@ impl PushComputed for Vec { // These are helpers that tests use to build Schema instances. #[cfg(test)] -fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) { +fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) { schema.entid_map.insert(e, i.clone()); schema.ident_map.insert(i.clone(), e); } @@ -1167,7 +1167,7 @@ fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) { #[cfg(test)] pub(crate) fn ident(ns: &str, name: &str) -> PatternNonValuePlace { - NamespacedKeyword::new(ns, name).into() + Keyword::namespaced(ns, name).into() } #[cfg(test)] diff --git a/query-algebrizer/src/clauses/not.rs b/query-algebrizer/src/clauses/not.rs index 6ab4e8e6..4d312023 100644 --- a/query-algebrizer/src/clauses/not.rs +++ b/query-algebrizer/src/clauses/not.rs @@ -101,7 +101,7 @@ mod testing { }; use mentat_query::{ - NamespacedKeyword, + Keyword, PlainSymbol, Variable }; @@ -151,11 +151,11 @@ mod testing { fn prepopulated_schema() -> Schema { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "knows"), 66); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69); + associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65); + associate_ident(&mut schema, Keyword::namespaced("foo", "knows"), 66); + associate_ident(&mut schema, Keyword::namespaced("foo", "parent"), 67); + associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68); + associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69); add_attribute(&mut schema, 65, Attribute { diff --git a/query-algebrizer/src/clauses/or.rs b/query-algebrizer/src/clauses/or.rs index e54be351..39e8208f 100644 --- a/query-algebrizer/src/clauses/or.rs +++ b/query-algebrizer/src/clauses/or.rs @@ -763,7 +763,7 @@ mod testing { }; use mentat_query::{ - NamespacedKeyword, + Keyword, Variable, }; @@ -810,11 +810,11 @@ mod testing { fn prepopulated_schema() -> Schema { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "knows"), 66); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69); + associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65); + associate_ident(&mut schema, Keyword::namespaced("foo", "knows"), 66); + associate_ident(&mut schema, Keyword::namespaced("foo", "parent"), 67); + associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68); + associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69); add_attribute(&mut schema, 65, Attribute { value_type: ValueType::String, multival: false, @@ -855,7 +855,7 @@ mod testing { [?x :foo/nope3 "Daphne"])]"#; let cc = alg(known, query); assert!(cc.is_known_empty()); - assert_eq!(cc.empty_because, Some(EmptyBecause::UnresolvedIdent(NamespacedKeyword::new("foo", "nope3")))); + assert_eq!(cc.empty_because, Some(EmptyBecause::UnresolvedIdent(Keyword::namespaced("foo", "nope3")))); } /// Test that if only one of the attributes in an `or` resolves, it's equivalent to a simple query. diff --git a/query-algebrizer/src/clauses/pattern.rs b/query-algebrizer/src/clauses/pattern.rs index 05b08c24..e338c392 100644 --- a/query-algebrizer/src/clauses/pattern.rs +++ b/query-algebrizer/src/clauses/pattern.rs @@ -654,7 +654,7 @@ mod testing { }; use mentat_query::{ - NamespacedKeyword, + Keyword, NonIntegerConstant, Variable, }; @@ -709,7 +709,7 @@ mod testing { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); let known = Known::for_schema(&schema); cc.apply_parsed_pattern(known, Pattern { @@ -728,7 +728,7 @@ mod testing { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Boolean, ..Default::default() @@ -814,7 +814,7 @@ mod testing { fn test_apply_unattributed_but_bound_pattern_with_returned() { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Boolean, ..Default::default() @@ -962,8 +962,8 @@ mod testing { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "roz"), 98); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "roz"), 98); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Boolean, ..Default::default() @@ -1035,7 +1035,7 @@ mod testing { fn test_value_bindings() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Boolean, ..Default::default() @@ -1083,7 +1083,7 @@ mod testing { fn test_value_bindings_type_disagreement() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Boolean, ..Default::default() @@ -1117,7 +1117,7 @@ mod testing { fn test_fulltext_type_disagreement() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::String, index: true, @@ -1155,8 +1155,8 @@ mod testing { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "roz"), 98); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "roz"), 98); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Boolean, ..Default::default() @@ -1244,7 +1244,7 @@ mod testing { fn ensure_extracted_types_is_cleared() { let query = r#"[:find ?e ?v :where [_ _ ?v] [?e :foo/bar ?v]]"#; let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Boolean, ..Default::default() diff --git a/query-algebrizer/src/clauses/predicate.rs b/query-algebrizer/src/clauses/predicate.rs index 986c78e4..f099b7b8 100644 --- a/query-algebrizer/src/clauses/predicate.rs +++ b/query-algebrizer/src/clauses/predicate.rs @@ -192,7 +192,7 @@ mod testing { use mentat_query::{ FnArg, - NamespacedKeyword, + Keyword, Pattern, PatternNonValuePlace, PatternValuePlace, @@ -220,7 +220,7 @@ mod testing { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Long, ..Default::default() @@ -238,8 +238,8 @@ mod testing { }); assert!(!cc.is_known_empty()); - let op = PlainSymbol::new("<"); - let comp = Inequality::from_datalog_operator(op.plain_name()).unwrap(); + let op = PlainSymbol::plain("<"); + let comp = Inequality::from_datalog_operator(op.name()).unwrap(); assert!(cc.apply_inequality(known, comp, Predicate { operator: op, args: vec![ @@ -275,8 +275,8 @@ mod testing { let mut cc = ConjoiningClauses::default(); let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "roz"), 98); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "roz"), 98); add_attribute(&mut schema, 99, Attribute { value_type: ValueType::Long, ..Default::default() @@ -299,8 +299,8 @@ mod testing { }); assert!(!cc.is_known_empty()); - let op = PlainSymbol::new(">="); - let comp = Inequality::from_datalog_operator(op.plain_name()).unwrap(); + let op = PlainSymbol::plain(">="); + let comp = Inequality::from_datalog_operator(op.name()).unwrap(); assert!(cc.apply_inequality(known, comp, Predicate { operator: op, args: vec![ diff --git a/query-algebrizer/src/clauses/tx_log_api.rs b/query-algebrizer/src/clauses/tx_log_api.rs index 1a947c86..2fc7dce8 100644 --- a/query-algebrizer/src/clauses/tx_log_api.rs +++ b/query-algebrizer/src/clauses/tx_log_api.rs @@ -268,7 +268,7 @@ mod testing { let known = Known::for_schema(&schema); - let op = PlainSymbol::new("tx-ids"); + let op = PlainSymbol::plain("tx-ids"); cc.apply_tx_ids(known, WhereFn { operator: op, args: vec![ @@ -323,7 +323,7 @@ mod testing { let known = Known::for_schema(&schema); - let op = PlainSymbol::new("tx-data"); + let op = PlainSymbol::plain("tx-data"); cc.apply_tx_data(known, WhereFn { operator: op, args: vec![ diff --git a/query-algebrizer/src/types.rs b/query-algebrizer/src/types.rs index b8b75322..5f226be0 100644 --- a/query-algebrizer/src/types.rs +++ b/query-algebrizer/src/types.rs @@ -25,7 +25,7 @@ use mentat_core::{ use mentat_query::{ Direction, - NamespacedKeyword, + Keyword, Order, SrcVar, Variable, @@ -617,8 +617,8 @@ pub enum EmptyBecause { NonEntityArgument, NonStringFulltextValue, NonFulltextAttribute(Entid), - UnresolvedIdent(NamespacedKeyword), - InvalidAttributeIdent(NamespacedKeyword), + UnresolvedIdent(Keyword), + InvalidAttributeIdent(Keyword), InvalidAttributeEntid(Entid), InvalidBinding(Column, TypedValue), ValueTypeMismatch(ValueType, TypedValue), @@ -708,7 +708,7 @@ pub enum EvolvedValuePlace { Entid(Entid), Value(TypedValue), EntidOrInteger(i64), - IdentOrKeyword(ValueRc), + IdentOrKeyword(ValueRc), } pub enum PlaceOrEmpty { diff --git a/query-algebrizer/src/validate.rs b/query-algebrizer/src/validate.rs index 56c0c11a..ddae881f 100644 --- a/query-algebrizer/src/validate.rs +++ b/query-algebrizer/src/validate.rs @@ -100,7 +100,7 @@ mod tests { use self::mentat_query::{ FindQuery, - NamespacedKeyword, + Keyword, OrWhereClause, Pattern, PatternNonValuePlace, @@ -120,7 +120,7 @@ mod tests { }; fn value_ident(ns: &str, name: &str) -> PatternValuePlace { - NamespacedKeyword::new(ns, name).into() + Keyword::namespaced(ns, name).into() } /// Tests that the top-level form is a valid `or`, returning the clauses. diff --git a/query-algebrizer/tests/fulltext.rs b/query-algebrizer/tests/fulltext.rs index 40f7f320..083f7121 100644 --- a/query-algebrizer/tests/fulltext.rs +++ b/query-algebrizer/tests/fulltext.rs @@ -22,7 +22,7 @@ use mentat_core::{ }; use mentat_query::{ - NamespacedKeyword, + Keyword, }; use utils::{ @@ -35,11 +35,11 @@ use mentat_query_algebrizer::Known; fn prepopulated_schema() -> Schema { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "description"), 66); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69); + associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65); + associate_ident(&mut schema, Keyword::namespaced("foo", "description"), 66); + associate_ident(&mut schema, Keyword::namespaced("foo", "parent"), 67); + associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68); + associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69); add_attribute(&mut schema, 65, Attribute { value_type: ValueType::String, multival: false, diff --git a/query-algebrizer/tests/ground.rs b/query-algebrizer/tests/ground.rs index 3ec68fb0..150b031e 100644 --- a/query-algebrizer/tests/ground.rs +++ b/query-algebrizer/tests/ground.rs @@ -25,7 +25,7 @@ use mentat_core::{ }; use mentat_query::{ - NamespacedKeyword, + Keyword, PlainSymbol, Variable, }; @@ -49,11 +49,11 @@ use utils::{ fn prepopulated_schema() -> Schema { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "knows"), 66); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69); + associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65); + associate_ident(&mut schema, Keyword::namespaced("foo", "knows"), 66); + associate_ident(&mut schema, Keyword::namespaced("foo", "parent"), 67); + associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68); + associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69); add_attribute(&mut schema, 65, Attribute { value_type: ValueType::String, multival: false, @@ -276,7 +276,7 @@ fn test_ground_tuple_duplicate_vars() { let e = bails(known, &q); match e { Error(ErrorKind::InvalidBinding(v, e), _) => { - assert_eq!(v, PlainSymbol::new("ground")); + assert_eq!(v, PlainSymbol::plain("ground")); assert_eq!(e, BindingError::RepeatedBoundVariable); }, _ => { @@ -293,7 +293,7 @@ fn test_ground_rel_duplicate_vars() { let e = bails(known, &q); match e { Error(ErrorKind::InvalidBinding(v, e), _) => { - assert_eq!(v, PlainSymbol::new("ground")); + assert_eq!(v, PlainSymbol::plain("ground")); assert_eq!(e, BindingError::RepeatedBoundVariable); }, _ => { diff --git a/query-algebrizer/tests/predicate.rs b/query-algebrizer/tests/predicate.rs index 42d4e25e..7482deed 100644 --- a/query-algebrizer/tests/predicate.rs +++ b/query-algebrizer/tests/predicate.rs @@ -26,7 +26,7 @@ use mentat_core::{ }; use mentat_query::{ - NamespacedKeyword, + Keyword, PlainSymbol, Variable, }; @@ -48,9 +48,9 @@ use utils::{ fn prepopulated_schema() -> Schema { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "date"), 65); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "double"), 66); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "long"), 67); + associate_ident(&mut schema, Keyword::namespaced("foo", "date"), 65); + associate_ident(&mut schema, Keyword::namespaced("foo", "double"), 66); + associate_ident(&mut schema, Keyword::namespaced("foo", "long"), 67); add_attribute(&mut schema, 65, Attribute { value_type: ValueType::Instant, multival: false, @@ -81,7 +81,7 @@ fn test_instant_predicates_require_instants() { [(> ?t "2017-06-16T00:56:41.257Z")]]"#; match bails(known, query).0 { ErrorKind::InvalidArgumentType(op, why, idx) => { - assert_eq!(op, PlainSymbol::new(">")); + assert_eq!(op, PlainSymbol::plain(">")); assert_eq!(why, ValueTypeSet::of_numeric_and_instant_types()); assert_eq!(idx, 1); }, @@ -94,7 +94,7 @@ fn test_instant_predicates_require_instants() { [(> "2017-06-16T00:56:41.257Z", ?t)]]"#; match bails(known, query).0 { ErrorKind::InvalidArgumentType(op, why, idx) => { - assert_eq!(op, PlainSymbol::new(">")); + assert_eq!(op, PlainSymbol::plain(">")); assert_eq!(why, ValueTypeSet::of_numeric_and_instant_types()); assert_eq!(idx, 0); // We get this right. }, diff --git a/query-algebrizer/tests/utils/mod.rs b/query-algebrizer/tests/utils/mod.rs index 35864beb..a643c556 100644 --- a/query-algebrizer/tests/utils/mod.rs +++ b/query-algebrizer/tests/utils/mod.rs @@ -25,7 +25,7 @@ use mentat_query_parser::{ }; use mentat_query::{ - NamespacedKeyword, + Keyword, }; use mentat_query_algebrizer::{ @@ -40,7 +40,7 @@ use mentat_query_algebrizer::{ // Common utility functions used in multiple test files. // These are helpers that tests use to build Schema instances. -pub fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) { +pub fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) { schema.entid_map.insert(e, i.clone()); schema.ident_map.insert(i.clone(), e); } @@ -62,7 +62,7 @@ impl SchemaBuilder { } } - pub fn define_attr(mut self, kw: NamespacedKeyword, attr: Attribute) -> Self { + pub fn define_attr(mut self, kw: Keyword, attr: Attribute) -> Self { associate_ident(&mut self.schema, kw, self.counter); add_attribute(&mut self.schema, self.counter, attr); self.counter += 1; @@ -74,9 +74,9 @@ impl SchemaBuilder { keyword_name: T, value_type: ValueType, multival: bool) -> Self - where T: Into + where T: AsRef { - self.define_attr(NamespacedKeyword::new(keyword_ns, keyword_name), Attribute { + self.define_attr(Keyword::namespaced(keyword_ns, keyword_name), Attribute { value_type, multival, ..Default::default() diff --git a/query-parser/src/parse.rs b/query-parser/src/parse.rs index 4ba5aca1..9cbaf4b2 100644 --- a/query-parser/src/parse.rs +++ b/query-parser/src/parse.rs @@ -734,22 +734,22 @@ mod test { Variable(Rc::new(x)) } - fn ident_kw(kw: edn::NamespacedKeyword) -> PatternNonValuePlace { + fn ident_kw(kw: edn::Keyword) -> PatternNonValuePlace { PatternNonValuePlace::Ident(kw.into()) } fn ident(ns: &str, name: &str) -> PatternNonValuePlace { - ident_kw(edn::NamespacedKeyword::new(ns, name)) + ident_kw(edn::Keyword::namespaced(ns, name)) } #[test] fn test_pattern_mixed() { - let e = edn::PlainSymbol::new("_"); - let a = edn::NamespacedKeyword::new("foo", "bar"); + let e = edn::PlainSymbol::plain("_"); + let a = edn::Keyword::namespaced("foo", "bar"); let v = OrderedFloat(99.9); - let tx = edn::PlainSymbol::new("?tx"); + let tx = edn::PlainSymbol::plain("?tx"); let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()), - edn::Value::NamespacedKeyword(a.clone()), + edn::Value::Keyword(a.clone()), edn::Value::Float(v.clone()), edn::Value::PlainSymbol(tx.clone()))); assert_parses_to!(Where::pattern, input, WhereClause::Pattern(Pattern { @@ -763,11 +763,11 @@ mod test { #[test] fn test_pattern_vars() { - let s = edn::PlainSymbol::new("$x"); - let e = edn::PlainSymbol::new("?e"); - let a = edn::PlainSymbol::new("?a"); - let v = edn::PlainSymbol::new("?v"); - let tx = edn::PlainSymbol::new("?tx"); + let s = edn::PlainSymbol::plain("$x"); + let e = edn::PlainSymbol::plain("?e"); + let a = edn::PlainSymbol::plain("?a"); + let v = edn::PlainSymbol::plain("?v"); + let tx = edn::PlainSymbol::plain("?tx"); let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(s.clone()), edn::Value::PlainSymbol(e.clone()), edn::Value::PlainSymbol(a.clone()), @@ -784,12 +784,12 @@ mod test { #[test] fn test_pattern_reversed_invalid() { - let e = edn::PlainSymbol::new("_"); - let a = edn::NamespacedKeyword::new("foo", "_bar"); + let e = edn::PlainSymbol::plain("_"); + let a = edn::Keyword::namespaced("foo", "_bar"); let v = OrderedFloat(99.9); - let tx = edn::PlainSymbol::new("?tx"); + let tx = edn::PlainSymbol::plain("?tx"); let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()), - edn::Value::NamespacedKeyword(a.clone()), + edn::Value::Keyword(a.clone()), edn::Value::Float(v.clone()), edn::Value::PlainSymbol(tx.clone()))); @@ -801,12 +801,12 @@ mod test { #[test] fn test_pattern_reversed() { - let e = edn::PlainSymbol::new("_"); - let a = edn::NamespacedKeyword::new("foo", "_bar"); - let v = edn::PlainSymbol::new("?v"); - let tx = edn::PlainSymbol::new("?tx"); + let e = edn::PlainSymbol::plain("_"); + let a = edn::Keyword::namespaced("foo", "_bar"); + let v = edn::PlainSymbol::plain("?v"); + let tx = edn::PlainSymbol::plain("?tx"); let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()), - edn::Value::NamespacedKeyword(a.clone()), + edn::Value::Keyword(a.clone()), edn::Value::PlainSymbol(v.clone()), edn::Value::PlainSymbol(tx.clone()))); @@ -823,7 +823,7 @@ mod test { #[test] fn test_rule_vars() { - let e = edn::PlainSymbol::new("?e"); + let e = edn::PlainSymbol::plain("?e"); let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone())]); assert_parses_to!(Where::rule_vars, input, btreeset!{variable(e.clone())}); @@ -831,14 +831,14 @@ mod test { #[test] fn test_repeated_vars() { - let e = edn::PlainSymbol::new("?e"); - let f = edn::PlainSymbol::new("?f"); + let e = edn::PlainSymbol::plain("?e"); + let f = edn::PlainSymbol::plain("?f"); let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone()), edn::Value::PlainSymbol(f.clone()),]); assert_parses_to!(|| vector().of_exactly(Find::vars()), input, btreeset!{variable(e.clone()), variable(f.clone())}); - let g = edn::PlainSymbol::new("?g"); + let g = edn::PlainSymbol::plain("?g"); let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(g.clone()), edn::Value::PlainSymbol(g.clone()),]); @@ -859,10 +859,10 @@ mod test { #[test] fn test_or() { - let oj = edn::PlainSymbol::new("or"); - let e = edn::PlainSymbol::new("?e"); - let a = edn::PlainSymbol::new("?a"); - let v = edn::PlainSymbol::new("?v"); + let oj = edn::PlainSymbol::plain("or"); + let e = edn::PlainSymbol::plain("?e"); + let a = edn::PlainSymbol::plain("?a"); + let v = edn::PlainSymbol::plain("?v"); let input = edn::Value::List( vec![edn::Value::PlainSymbol(oj), edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone()), @@ -883,10 +883,10 @@ mod test { #[test] fn test_or_join() { - let oj = edn::PlainSymbol::new("or-join"); - let e = edn::PlainSymbol::new("?e"); - let a = edn::PlainSymbol::new("?a"); - let v = edn::PlainSymbol::new("?v"); + let oj = edn::PlainSymbol::plain("or-join"); + let e = edn::PlainSymbol::plain("?e"); + let a = edn::PlainSymbol::plain("?a"); + let v = edn::PlainSymbol::plain("?v"); let input = edn::Value::List( vec![edn::Value::PlainSymbol(oj), edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone())]), @@ -908,9 +908,9 @@ mod test { #[test] fn test_not() { - let e = edn::PlainSymbol::new("?e"); - let a = edn::PlainSymbol::new("?a"); - let v = edn::PlainSymbol::new("?v"); + let e = edn::PlainSymbol::plain("?e"); + let a = edn::PlainSymbol::plain("?a"); + let v = edn::PlainSymbol::plain("?v"); assert_edn_parses_to!(Where::not_clause, "(not [?e ?a ?v])", @@ -930,9 +930,9 @@ mod test { #[test] fn test_not_join() { - let e = edn::PlainSymbol::new("?e"); - let a = edn::PlainSymbol::new("?a"); - let v = edn::PlainSymbol::new("?v"); + let e = edn::PlainSymbol::plain("?e"); + let a = edn::PlainSymbol::plain("?a"); + let v = edn::PlainSymbol::plain("?v"); assert_edn_parses_to!(Where::not_join_clause, "(not-join [?e] [?e ?a ?v])", @@ -951,15 +951,15 @@ mod test { #[test] fn test_find_sp_variable() { - let sym = edn::PlainSymbol::new("?x"); + let sym = edn::PlainSymbol::plain("?x"); let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone())]); assert_parses_to!(|| vector().of_exactly(Query::variable()), input, variable(sym)); } #[test] fn test_find_scalar() { - let sym = edn::PlainSymbol::new("?x"); - let period = edn::PlainSymbol::new("."); + let sym = edn::PlainSymbol::plain("?x"); + let period = edn::PlainSymbol::plain("."); let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone()), edn::Value::PlainSymbol(period.clone())]); assert_parses_to!(|| vector().of_exactly(Find::find_scalar()), input, @@ -968,8 +968,8 @@ mod test { #[test] fn test_find_coll() { - let sym = edn::PlainSymbol::new("?x"); - let period = edn::PlainSymbol::new("..."); + let sym = edn::PlainSymbol::plain("?x"); + let period = edn::PlainSymbol::plain("..."); let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone()), edn::Value::PlainSymbol(period.clone())]); assert_parses_to!(Find::find_coll, @@ -979,8 +979,8 @@ mod test { #[test] fn test_find_rel() { - let vx = edn::PlainSymbol::new("?x"); - let vy = edn::PlainSymbol::new("?y"); + let vx = edn::PlainSymbol::plain("?x"); + let vy = edn::PlainSymbol::plain("?y"); let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()), edn::Value::PlainSymbol(vy.clone())]); assert_parses_to!(|| vector().of_exactly(Find::find_rel()), input, @@ -990,8 +990,8 @@ mod test { #[test] fn test_find_tuple() { - let vx = edn::PlainSymbol::new("?x"); - let vy = edn::PlainSymbol::new("?y"); + let vx = edn::PlainSymbol::plain("?x"); + let vy = edn::PlainSymbol::plain("?y"); let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()), edn::Value::PlainSymbol(vy.clone())]); assert_parses_to!(Find::find_tuple, @@ -1033,8 +1033,8 @@ mod test { #[test] fn test_fn_arg_collections() { - let vx = edn::PlainSymbol::new("?x"); - let vy = edn::PlainSymbol::new("?y"); + let vx = edn::PlainSymbol::plain("?x"); + let vy = edn::PlainSymbol::plain("?y"); let input = edn::Value::Vector(vec![edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()), edn::Value::PlainSymbol(vy.clone())])]); @@ -1047,7 +1047,7 @@ mod test { #[test] fn test_bind_scalar() { - let vx = edn::PlainSymbol::new("?x"); + let vx = edn::PlainSymbol::plain("?x"); assert_edn_parses_to!(|| list().of_exactly(Bind::binding()), "(?x)", Binding::BindScalar(variable(vx))); @@ -1055,7 +1055,7 @@ mod test { #[test] fn test_bind_coll() { - let vx = edn::PlainSymbol::new("?x"); + let vx = edn::PlainSymbol::plain("?x"); assert_edn_parses_to!(|| list().of_exactly(Bind::binding()), "([?x ...])", Binding::BindColl(variable(vx))); @@ -1063,9 +1063,9 @@ mod test { #[test] fn test_bind_rel() { - let vx = edn::PlainSymbol::new("?x"); - let vy = edn::PlainSymbol::new("?y"); - let vw = edn::PlainSymbol::new("?w"); + let vx = edn::PlainSymbol::plain("?x"); + let vy = edn::PlainSymbol::plain("?y"); + let vw = edn::PlainSymbol::plain("?w"); assert_edn_parses_to!(|| list().of_exactly(Bind::binding()), "([[?x ?y _ ?w]])", Binding::BindRel(vec![VariableOrPlaceholder::Variable(variable(vx)), @@ -1077,9 +1077,9 @@ mod test { #[test] fn test_bind_tuple() { - let vx = edn::PlainSymbol::new("?x"); - let vy = edn::PlainSymbol::new("?y"); - let vw = edn::PlainSymbol::new("?w"); + let vx = edn::PlainSymbol::plain("?x"); + let vy = edn::PlainSymbol::plain("?y"); + let vw = edn::PlainSymbol::plain("?w"); assert_edn_parses_to!(|| list().of_exactly(Bind::binding()), "([?x ?y _ ?w])", Binding::BindTuple(vec![VariableOrPlaceholder::Variable(variable(vx)), @@ -1138,7 +1138,7 @@ mod test { assert_edn_parses_to!(Where::where_fn, "[(f ?x 1) ?y]", WhereClause::WhereFn(WhereFn { - operator: edn::PlainSymbol::new("f"), + operator: edn::PlainSymbol::plain("f"), args: vec![FnArg::Variable(Variable::from_valid_name("?x")), FnArg::EntidOrInteger(1)], binding: Binding::BindScalar(Variable::from_valid_name("?y")), @@ -1147,7 +1147,7 @@ mod test { assert_edn_parses_to!(Where::where_fn, "[(f ?x) [?y ...]]", WhereClause::WhereFn(WhereFn { - operator: edn::PlainSymbol::new("f"), + operator: edn::PlainSymbol::plain("f"), args: vec![FnArg::Variable(Variable::from_valid_name("?x"))], binding: Binding::BindColl(Variable::from_valid_name("?y")), })); @@ -1155,7 +1155,7 @@ mod test { assert_edn_parses_to!(Where::where_fn, "[(f) [?y _]]", WhereClause::WhereFn(WhereFn { - operator: edn::PlainSymbol::new("f"), + operator: edn::PlainSymbol::plain("f"), args: vec![], binding: Binding::BindTuple(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?y")), VariableOrPlaceholder::Placeholder]), @@ -1164,7 +1164,7 @@ mod test { assert_edn_parses_to!(Where::where_fn, "[(f) [[_ ?y]]]", WhereClause::WhereFn(WhereFn { - operator: edn::PlainSymbol::new("f"), + operator: edn::PlainSymbol::plain("f"), args: vec![], binding: Binding::BindRel(vec![VariableOrPlaceholder::Placeholder, VariableOrPlaceholder::Variable(Variable::from_valid_name("?y"))]), @@ -1203,8 +1203,8 @@ mod test { patterns: vec![PullAttributeSpec::Wildcard], })); - let foo_bar = ::std::rc::Rc::new(edn::NamespacedKeyword::new("foo", "bar")); - let foo_baz = ::std::rc::Rc::new(edn::NamespacedKeyword::new("foo", "baz")); + let foo_bar = ::std::rc::Rc::new(edn::Keyword::namespaced("foo", "bar")); + let foo_baz = ::std::rc::Rc::new(edn::Keyword::namespaced("foo", "baz")); assert_edn_parses_to!(Query::pull_concrete_attribute, ":foo/bar", PullAttributeSpec::Attribute( @@ -1241,7 +1241,7 @@ mod test { patterns: vec![ PullAttributeSpec::Attribute( PullConcreteAttribute::Ident( - ::std::rc::Rc::new(edn::NamespacedKeyword::new("foo", "bar")) + ::std::rc::Rc::new(edn::Keyword::namespaced("foo", "bar")) ) ), ] })]), diff --git a/query-parser/tests/find_tests.rs b/query-parser/tests/find_tests.rs index a911177c..e274e6ff 100644 --- a/query-parser/tests/find_tests.rs +++ b/query-parser/tests/find_tests.rs @@ -17,7 +17,7 @@ extern crate mentat_query; extern crate mentat_query_parser; use edn::{ - NamespacedKeyword, + Keyword, PlainSymbol, }; @@ -63,7 +63,7 @@ fn can_parse_predicates() { value: PatternValuePlace::Variable(Variable::from_valid_name("?y")), tx: PatternNonValuePlace::Placeholder, }), - WhereClause::Pred(Predicate { operator: PlainSymbol::new("<"), args: vec![ + WhereClause::Pred(Predicate { operator: PlainSymbol::plain("<"), args: vec![ FnArg::Variable(Variable::from_valid_name("?y")), FnArg::EntidOrInteger(10), ]}), ]); @@ -162,7 +162,7 @@ fn can_parse_simple_or_join() { #[cfg(test)] fn ident(ns: &str, name: &str) -> PatternNonValuePlace { - NamespacedKeyword::new(ns, name).into() + Keyword::namespaced(ns, name).into() } #[test] @@ -207,7 +207,7 @@ fn can_parse_simple_or_and_join() { ], )), - WhereClause::Pred(Predicate { operator: PlainSymbol::new("<"), args: vec![ + WhereClause::Pred(Predicate { operator: PlainSymbol::plain("<"), args: vec![ FnArg::Variable(Variable::from_valid_name("?y")), FnArg::EntidOrInteger(1), ]}), ], @@ -281,7 +281,7 @@ fn can_parse_uuid() { WhereClause::Pattern( Pattern::new(None, PatternNonValuePlace::Variable(Variable::from_valid_name("?x")), - NamespacedKeyword::new("foo", "baz").into(), + Keyword::namespaced("foo", "baz").into(), PatternValuePlace::Constant(NonIntegerConstant::Uuid(expected)), PatternNonValuePlace::Placeholder) .expect("valid pattern"))); diff --git a/query-projector/src/aggregates.rs b/query-projector/src/aggregates.rs index 540f6e27..6bd011b8 100644 --- a/query-projector/src/aggregates.rs +++ b/query-projector/src/aggregates.rs @@ -59,7 +59,7 @@ impl SimpleAggregationOp { } fn for_function(function: &QueryFunction) -> Option { - match function.0.plain_name() { + match function.0.name() { "avg" => Some(SimpleAggregationOp::Avg), "count" => Some(SimpleAggregationOp::Count), "max" => Some(SimpleAggregationOp::Max), diff --git a/query-projector/tests/aggregates.rs b/query-projector/tests/aggregates.rs index 1a18db81..c1313ea6 100644 --- a/query-projector/tests/aggregates.rs +++ b/query-projector/tests/aggregates.rs @@ -26,7 +26,7 @@ use mentat_query_parser::{ }; use mentat_query::{ - NamespacedKeyword, + Keyword, }; use mentat_query_algebrizer::{ @@ -39,7 +39,7 @@ use mentat_query_projector::{ }; // These are helpers that tests use to build Schema instances. -fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) { +fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) { schema.entid_map.insert(e, i.clone()); schema.ident_map.insert(i.clone(), e); } @@ -50,9 +50,9 @@ fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) { fn prepopulated_schema() -> Schema { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69); + associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65); + associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68); + associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69); add_attribute(&mut schema, 65, Attribute { value_type: ValueType::String, multival: false, diff --git a/query-pull/src/lib.rs b/query-pull/src/lib.rs index a011ac51..7138ddc5 100644 --- a/query-pull/src/lib.rs +++ b/query-pull/src/lib.rs @@ -82,7 +82,7 @@ use mentat_core::{ Cloned, Entid, HasSchema, - NamespacedKeyword, + Keyword, Schema, StructuredMap, ValueRc, @@ -140,7 +140,7 @@ pub fn pull_attributes_for_entities(schema: &Schema, pub struct Puller { // The domain of this map is the set of attributes to fetch. // The range is the set of aliases to use in the output. - attributes: BTreeMap>, + attributes: BTreeMap>, attribute_spec: cache::AttributeSpec, } @@ -163,7 +163,7 @@ impl Puller { .ok_or_else(|| ErrorKind::UnnamedAttribute(*i)) }; - let mut names: BTreeMap> = Default::default(); + let mut names: BTreeMap> = Default::default(); let mut attrs: BTreeSet = Default::default(); for attr in attributes.iter() { match attr { diff --git a/query-translator/tests/translate.rs b/query-translator/tests/translate.rs index 101810f1..1b2bb982 100644 --- a/query-translator/tests/translate.rs +++ b/query-translator/tests/translate.rs @@ -22,7 +22,7 @@ use std::rc::Rc; use mentat_query::{ FindSpec, - NamespacedKeyword, + Keyword, Variable, }; @@ -62,7 +62,7 @@ macro_rules! var { }; } -fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) { +fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) { schema.entid_map.insert(e, i.clone()); schema.ident_map.insert(i.clone(), e); } @@ -123,12 +123,12 @@ fn translate_to_constant(schema: &Schema, query: &'static str) -> ConstantProjec fn prepopulated_typed_schema(foo_type: ValueType) -> Schema { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99); + associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99); add_attribute(&mut schema, 99, Attribute { value_type: foo_type, ..Default::default() }); - associate_ident(&mut schema, NamespacedKeyword::new("foo", "fts"), 100); + associate_ident(&mut schema, Keyword::namespaced("foo", "fts"), 100); add_attribute(&mut schema, 100, Attribute { value_type: ValueType::String, index: true, @@ -486,9 +486,9 @@ fn test_compare_double_to_long() { #[test] fn test_simple_or_join() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("page", "url"), 97); - associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98); - associate_ident(&mut schema, NamespacedKeyword::new("page", "description"), 99); + associate_ident(&mut schema, Keyword::namespaced("page", "url"), 97); + associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98); + associate_ident(&mut schema, Keyword::namespaced("page", "description"), 99); for x in 97..100 { add_attribute(&mut schema, x, Attribute { value_type: ValueType::String, @@ -511,16 +511,16 @@ fn test_simple_or_join() { #[test] fn test_complex_or_join() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("page", "save"), 95); + associate_ident(&mut schema, Keyword::namespaced("page", "save"), 95); add_attribute(&mut schema, 95, Attribute { value_type: ValueType::Ref, ..Default::default() }); - associate_ident(&mut schema, NamespacedKeyword::new("save", "title"), 96); - associate_ident(&mut schema, NamespacedKeyword::new("page", "url"), 97); - associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98); - associate_ident(&mut schema, NamespacedKeyword::new("page", "description"), 99); + associate_ident(&mut schema, Keyword::namespaced("save", "title"), 96); + associate_ident(&mut schema, Keyword::namespaced("page", "url"), 97); + associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98); + associate_ident(&mut schema, Keyword::namespaced("page", "description"), 99); for x in 96..100 { add_attribute(&mut schema, x, Attribute { value_type: ValueType::String, @@ -572,7 +572,7 @@ fn test_complex_or_join() { #[test] fn test_complex_or_join_type_projection() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98); + associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98); add_attribute(&mut schema, 98, Attribute { value_type: ValueType::String, ..Default::default() @@ -603,9 +603,9 @@ fn test_complex_or_join_type_projection() { #[test] fn test_not() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("page", "url"), 97); - associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98); - associate_ident(&mut schema, NamespacedKeyword::new("page", "bookmarked"), 99); + associate_ident(&mut schema, Keyword::namespaced("page", "url"), 97); + associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98); + associate_ident(&mut schema, Keyword::namespaced("page", "bookmarked"), 99); for x in 97..99 { add_attribute(&mut schema, x, Attribute { value_type: ValueType::String, @@ -629,9 +629,9 @@ fn test_not() { #[test] fn test_not_join() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("page", "url"), 97); - associate_ident(&mut schema, NamespacedKeyword::new("bookmarks", "page"), 98); - associate_ident(&mut schema, NamespacedKeyword::new("bookmarks", "date_created"), 99); + associate_ident(&mut schema, Keyword::namespaced("page", "url"), 97); + associate_ident(&mut schema, Keyword::namespaced("bookmarks", "page"), 98); + associate_ident(&mut schema, Keyword::namespaced("bookmarks", "date_created"), 99); add_attribute(&mut schema, 97, Attribute { value_type: ValueType::String, ..Default::default() @@ -698,7 +698,7 @@ fn test_order_by() { #[test] fn test_complex_nested_or_join_type_projection() { let mut schema = Schema::default(); - associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98); + associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98); add_attribute(&mut schema, 98, Attribute { value_type: ValueType::String, ..Default::default() @@ -884,10 +884,10 @@ fn test_unbound_attribute_with_ground() { #[test] fn test_not_with_ground() { let mut schema = prepopulated_schema(); - associate_ident(&mut schema, NamespacedKeyword::new("db", "valueType"), 7); - associate_ident(&mut schema, NamespacedKeyword::new("db.type", "ref"), 23); - associate_ident(&mut schema, NamespacedKeyword::new("db.type", "bool"), 28); - associate_ident(&mut schema, NamespacedKeyword::new("db.type", "instant"), 29); + associate_ident(&mut schema, Keyword::namespaced("db", "valueType"), 7); + associate_ident(&mut schema, Keyword::namespaced("db.type", "ref"), 23); + associate_ident(&mut schema, Keyword::namespaced("db.type", "bool"), 28); + associate_ident(&mut schema, Keyword::namespaced("db.type", "instant"), 29); add_attribute(&mut schema, 7, Attribute { value_type: ValueType::Ref, multival: false, @@ -1139,7 +1139,7 @@ fn test_tx_before_and_after() { #[test] fn test_tx_ids() { let mut schema = prepopulated_typed_schema(ValueType::Double); - associate_ident(&mut schema, NamespacedKeyword::new("db", "txInstant"), 101); + associate_ident(&mut schema, Keyword::namespaced("db", "txInstant"), 101); add_attribute(&mut schema, 101, Attribute { value_type: ValueType::Instant, multival: false, diff --git a/query/src/lib.rs b/query/src/lib.rs index 76e4e115..488c4f37 100644 --- a/query/src/lib.rs +++ b/query/src/lib.rs @@ -50,7 +50,7 @@ use edn::{ }; pub use edn::{ - NamespacedKeyword, + Keyword, PlainSymbol, }; @@ -81,7 +81,7 @@ impl Variable { /// Return a new `Variable`, assuming that the provided string is a valid name. pub fn from_valid_name(name: &str) -> Variable { - let s = PlainSymbol::new(name); + let s = PlainSymbol::plain(name); assert!(s.is_var_symbol()); Variable(Rc::new(s)) } @@ -193,7 +193,7 @@ impl SrcVar { if sym.0 == "$" { Some(SrcVar::DefaultSrc) } else { - Some(SrcVar::NamedSrc(sym.plain_name().to_string())) + Some(SrcVar::NamedSrc(sym.name().to_string())) } } else { None @@ -242,7 +242,7 @@ pub enum FnArg { Variable(Variable), SrcVar(SrcVar), EntidOrInteger(i64), - IdentOrKeyword(NamespacedKeyword), + IdentOrKeyword(Keyword), Constant(NonIntegerConstant), // The collection values representable in EDN. There's no advantage to destructuring up front, // since consumers will need to handle arbitrarily nested EDN themselves anyway. @@ -260,7 +260,7 @@ impl FromValue for FnArg { PlainSymbol(ref x) if x.is_var_symbol() => Variable::from_symbol(x).map(FnArg::Variable), PlainSymbol(_) => None, - NamespacedKeyword(ref x) => + Keyword(ref x) => Some(FnArg::IdentOrKeyword(x.clone())), Instant(x) => Some(FnArg::Constant(NonIntegerConstant::Instant(x))), @@ -277,7 +277,6 @@ impl FromValue for FnArg { Some(FnArg::Constant(x.clone().into())), Nil | NamespacedSymbol(_) | - Keyword(_) | Vector(_) | List(_) | Set(_) | @@ -326,17 +325,17 @@ pub enum PatternNonValuePlace { Placeholder, Variable(Variable), Entid(i64), // Will always be +ve. See #190. - Ident(ValueRc), + Ident(ValueRc), } -impl From> for PatternNonValuePlace { - fn from(value: Rc) -> Self { +impl From> for PatternNonValuePlace { + fn from(value: Rc) -> Self { PatternNonValuePlace::Ident(ValueRc::from_rc(value)) } } -impl From for PatternNonValuePlace { - fn from(value: NamespacedKeyword) -> Self { +impl From for PatternNonValuePlace { + fn from(value: Keyword) -> Self { PatternNonValuePlace::Ident(ValueRc::new(value)) } } @@ -380,7 +379,7 @@ impl FromValue for PatternNonValuePlace { None } }, - edn::SpannedValue::NamespacedKeyword(ref x) => + edn::SpannedValue::Keyword(ref x) => Some(x.clone().into()), _ => None, } @@ -389,7 +388,7 @@ impl FromValue for PatternNonValuePlace { #[derive(Clone, Debug, Eq, PartialEq)] pub enum IdentOrEntid { - Ident(NamespacedKeyword), + Ident(Keyword), Entid(i64), } @@ -401,18 +400,18 @@ pub enum PatternValuePlace { Placeholder, Variable(Variable), EntidOrInteger(i64), - IdentOrKeyword(ValueRc), + IdentOrKeyword(ValueRc), Constant(NonIntegerConstant), } -impl From> for PatternValuePlace { - fn from(value: Rc) -> Self { +impl From> for PatternValuePlace { + fn from(value: Rc) -> Self { PatternValuePlace::IdentOrKeyword(ValueRc::from_rc(value)) } } -impl From for PatternValuePlace { - fn from(value: NamespacedKeyword) -> Self { +impl From for PatternValuePlace { + fn from(value: Keyword) -> Self { PatternValuePlace::IdentOrKeyword(ValueRc::new(value)) } } @@ -426,7 +425,7 @@ impl FromValue for PatternValuePlace { Some(PatternValuePlace::Placeholder), edn::SpannedValue::PlainSymbol(ref x) => Variable::from_symbol(x).map(PatternValuePlace::Variable), - edn::SpannedValue::NamespacedKeyword(ref x) => + edn::SpannedValue::Keyword(ref x) if x.is_namespaced() => Some(x.clone().into()), edn::SpannedValue::Boolean(x) => Some(PatternValuePlace::Constant(NonIntegerConstant::Boolean(x))), @@ -445,7 +444,7 @@ impl FromValue for PatternValuePlace { // These don't appear in queries. edn::SpannedValue::Nil => None, edn::SpannedValue::NamespacedSymbol(_) => None, - edn::SpannedValue::Keyword(_) => None, + edn::SpannedValue::Keyword(_) => None, // … yet. edn::SpannedValue::Map(_) => None, edn::SpannedValue::List(_) => None, edn::SpannedValue::Set(_) => None, @@ -489,13 +488,13 @@ impl PatternValuePlace { // Not yet used. // pub enum PullDefaultValue { // EntidOrInteger(i64), -// IdentOrKeyword(Rc), +// IdentOrKeyword(Rc), // Constant(NonIntegerConstant), // } #[derive(Clone, Debug, Eq, PartialEq)] pub enum PullConcreteAttribute { - Ident(Rc), + Ident(Rc), Entid(i64), } diff --git a/src/conn.rs b/src/conn.rs index 1a965f7d..813afe74 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -47,7 +47,7 @@ use mentat_core::{ Entid, HasSchema, KnownEntid, - NamespacedKeyword, + Keyword, Schema, StructuredMap, TypedValue, @@ -215,9 +215,9 @@ pub trait Queryable { where T: Into>; fn q_prepare(&self, query: &str, inputs: T) -> PreparedResult where T: Into>; - fn lookup_values_for_attribute(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result> + fn lookup_values_for_attribute(&self, entity: E, attribute: &edn::Keyword) -> Result> where E: Into; - fn lookup_value_for_attribute(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result> + fn lookup_value_for_attribute(&self, entity: E, attribute: &edn::Keyword) -> Result> where E: Into; } @@ -269,12 +269,12 @@ impl<'a, 'c> Queryable for InProgressRead<'a, 'c> { self.0.q_explain(query, inputs) } - fn lookup_values_for_attribute(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result> + fn lookup_values_for_attribute(&self, entity: E, attribute: &edn::Keyword) -> Result> where E: Into { self.0.lookup_values_for_attribute(entity, attribute) } - fn lookup_value_for_attribute(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result> + fn lookup_value_for_attribute(&self, entity: E, attribute: &edn::Keyword) -> Result> where E: Into { self.0.lookup_value_for_attribute(entity, attribute) } @@ -331,13 +331,13 @@ impl<'a, 'c> Queryable for InProgress<'a, 'c> { inputs) } - fn lookup_values_for_attribute(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result> + fn lookup_values_for_attribute(&self, entity: E, attribute: &edn::Keyword) -> Result> where E: Into { let known = Known::new(&self.schema, Some(&self.cache)); lookup_values_for_attribute(&*(self.transaction), known, entity, attribute) } - fn lookup_value_for_attribute(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result> + fn lookup_value_for_attribute(&self, entity: E, attribute: &edn::Keyword) -> Result> where E: Into { let known = Known::new(&self.schema, Some(&self.cache)); lookup_value_for_attribute(&*(self.transaction), known, entity, attribute) @@ -364,11 +364,11 @@ impl<'a, 'c> HasSchema for InProgressRead<'a, 'c> { self.0.entid_for_type(t) } - fn get_ident(&self, x: T) -> Option<&NamespacedKeyword> where T: Into { + fn get_ident(&self, x: T) -> Option<&Keyword> where T: Into { self.0.get_ident(x) } - fn get_entid(&self, x: &NamespacedKeyword) -> Option { + fn get_entid(&self, x: &Keyword) -> Option { self.0.get_entid(x) } @@ -376,7 +376,7 @@ impl<'a, 'c> HasSchema for InProgressRead<'a, 'c> { self.0.attribute_for_entid(x) } - fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<(&Attribute, KnownEntid)> { + fn attribute_for_ident(&self, ident: &Keyword) -> Option<(&Attribute, KnownEntid)> { self.0.attribute_for_ident(ident) } @@ -386,7 +386,7 @@ impl<'a, 'c> HasSchema for InProgressRead<'a, 'c> { } /// Return true if the provided ident identifies an attribute in this schema. - fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool { + fn identifies_attribute(&self, x: &Keyword) -> bool { self.0.identifies_attribute(x) } @@ -400,11 +400,11 @@ impl<'a, 'c> HasSchema for InProgress<'a, 'c> { self.schema.entid_for_type(t) } - fn get_ident(&self, x: T) -> Option<&NamespacedKeyword> where T: Into { + fn get_ident(&self, x: T) -> Option<&Keyword> where T: Into { self.schema.get_ident(x) } - fn get_entid(&self, x: &NamespacedKeyword) -> Option { + fn get_entid(&self, x: &Keyword) -> Option { self.schema.get_entid(x) } @@ -412,7 +412,7 @@ impl<'a, 'c> HasSchema for InProgress<'a, 'c> { self.schema.attribute_for_entid(x) } - fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<(&Attribute, KnownEntid)> { + fn attribute_for_ident(&self, ident: &Keyword) -> Option<(&Attribute, KnownEntid)> { self.schema.attribute_for_ident(ident) } @@ -422,7 +422,7 @@ impl<'a, 'c> HasSchema for InProgress<'a, 'c> { } /// Return true if the provided ident identifies an attribute in this schema. - fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool { + fn identifies_attribute(&self, x: &Keyword) -> bool { self.schema.identifies_attribute(x) } @@ -549,7 +549,7 @@ impl<'a, 'c> InProgress<'a, 'c> { } pub fn cache(&mut self, - attribute: &NamespacedKeyword, + attribute: &Keyword, cache_direction: CacheDirection, cache_action: CacheAction) -> Result<()> { let attribute_entid: Entid = self.schema @@ -631,7 +631,7 @@ impl Store { self.conn.begin_transaction(&mut self.sqlite) } - pub fn cache(&mut self, attr: &NamespacedKeyword, direction: CacheDirection) -> Result<()> { + pub fn cache(&mut self, attr: &Keyword, direction: CacheDirection) -> Result<()> { let schema = &self.conn.current_schema(); self.conn.cache(&mut self.sqlite, schema, @@ -648,7 +648,7 @@ impl Store { self.conn.unregister_observer(key); } - pub fn assert_datom(&mut self, entid: T, attribute: NamespacedKeyword, value: TypedValue) -> Result<()> where T: Into { + pub fn assert_datom(&mut self, entid: T, attribute: Keyword, value: TypedValue) -> Result<()> where T: Into { self.conn.assert_datom(&mut self.sqlite, entid, attribute, value) } } @@ -669,12 +669,12 @@ impl Queryable for Store { self.conn.q_explain(&self.sqlite, query, inputs) } - fn lookup_values_for_attribute(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result> + fn lookup_values_for_attribute(&self, entity: E, attribute: &edn::Keyword) -> Result> where E: Into { self.conn.lookup_values_for_attribute(&self.sqlite, entity.into(), attribute) } - fn lookup_value_for_attribute(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result> + fn lookup_value_for_attribute(&self, entity: E, attribute: &edn::Keyword) -> Result> where E: Into { self.conn.lookup_value_for_attribute(&self.sqlite, entity.into(), attribute) } @@ -845,7 +845,7 @@ impl Conn { pub fn lookup_values_for_attribute(&self, sqlite: &rusqlite::Connection, entity: Entid, - attribute: &edn::NamespacedKeyword) -> Result> { + attribute: &edn::Keyword) -> Result> { let metadata = self.metadata.lock().unwrap(); let known = Known::new(&*metadata.schema, Some(&metadata.attribute_cache)); lookup_values_for_attribute(sqlite, known, entity, attribute) @@ -854,7 +854,7 @@ impl Conn { pub fn lookup_value_for_attribute(&self, sqlite: &rusqlite::Connection, entity: Entid, - attribute: &edn::NamespacedKeyword) -> Result> { + attribute: &edn::Keyword) -> Result> { let metadata = self.metadata.lock().unwrap(); let known = Known::new(&*metadata.schema, Some(&metadata.attribute_cache)); lookup_value_for_attribute(sqlite, known, entity, attribute) @@ -937,7 +937,7 @@ impl Conn { pub fn cache(&mut self, sqlite: &mut rusqlite::Connection, schema: &Schema, - attribute: &NamespacedKeyword, + attribute: &Keyword, cache_direction: CacheDirection, cache_action: CacheAction) -> Result<()> { let mut metadata = self.metadata.lock().unwrap(); @@ -977,7 +977,7 @@ impl Conn { // TODO: expose the entity builder over FFI and remove the need for this function entirely // It's really only here in order to keep the FFI layer as thin as possible. // Once the entity builder is exposed, we can perform all of these functions over FFI from the client. - pub fn assert_datom(&mut self, sqlite: &mut rusqlite::Connection, entid: T, attribute: NamespacedKeyword, value: TypedValue) -> Result<()> where T: Into { + pub fn assert_datom(&mut self, sqlite: &mut rusqlite::Connection, entid: T, attribute: Keyword, value: TypedValue) -> Result<()> where T: Into { let in_progress = self.begin_transaction(sqlite)?; let mut builder = in_progress.builder().describe(entid.into()); builder.add_kw(&attribute, value)?; @@ -1122,6 +1122,8 @@ mod tests { assert!(one == tempid_offset || one == tempid_offset + 1); assert!(two == tempid_offset || two == tempid_offset + 1); + println!("RES: {:?}", in_progress.q_once("[:find ?v :where [?x :db/ident ?v]]", None).unwrap()); + let during = in_progress.q_once("[:find ?x . :where [?x :db/ident :a/keyword1]]", None) .expect("query succeeded"); assert_eq!(during.results, QueryResults::Scalar(Some(TypedValue::Ref(one).into()))); @@ -1208,9 +1210,9 @@ mod tests { assert_eq!(during.results, QueryResults::Scalar(Some(TypedValue::Ref(one).into()))); // And we can do direct lookup, too. - let kw = in_progress.lookup_value_for_attribute(one, &edn::NamespacedKeyword::new("db", "ident")) + let kw = in_progress.lookup_value_for_attribute(one, &edn::Keyword::namespaced("db", "ident")) .expect("lookup succeeded"); - assert_eq!(kw, Some(TypedValue::Keyword(edn::NamespacedKeyword::new("a", "keyword1").into()))); + assert_eq!(kw, Some(TypedValue::Keyword(edn::Keyword::namespaced("a", "keyword1").into()))); in_progress.rollback() .expect("rollback succeeded"); diff --git a/src/entity_builder.rs b/src/entity_builder.rs index 5cac5d34..13516cdc 100644 --- a/src/entity_builder.rs +++ b/src/entity_builder.rs @@ -22,7 +22,7 @@ // Entity::AddOrRetract { // op: OpType::Add, // e: EntidOrLookupRefOrTempId::LookupRef(LookupRef { -// a: Entid::Ident(NamespacedKeyword::new("test", "a1")), +// a: Entid::Ident(Keyword::namespaced("test", "a1")), // v: Value::Text("v1".into()), // }), // a: Entid::Ident(kw!(:test/a)), @@ -56,7 +56,7 @@ use mentat_core::{ HasSchema, KnownEntid, - NamespacedKeyword, + Keyword, TypedValue, }; @@ -256,21 +256,21 @@ impl<'a, 'c> BuildTerms for InProgressBuilder<'a, 'c> { } impl<'a, 'c> InProgressBuilder<'a, 'c> { - pub fn add_kw(&mut self, e: E, a: &NamespacedKeyword, v: V) -> Result<()> + pub fn add_kw(&mut self, e: E, a: &Keyword, v: V) -> Result<()> where E: IntoThing>, V: IntoThing> { let (attribute, value) = self.extract_kw_value(a, v.into_thing())?; self.add(e, attribute, value) } - pub fn retract_kw(&mut self, e: E, a: &NamespacedKeyword, v: V) -> Result<()> + pub fn retract_kw(&mut self, e: E, a: &Keyword, v: V) -> Result<()> where E: IntoThing>, V: IntoThing> { let (attribute, value) = self.extract_kw_value(a, v.into_thing())?; self.retract(e, attribute, value) } - fn extract_kw_value(&mut self, a: &NamespacedKeyword, v: TypedValueOr) -> Result<(KnownEntid, TypedValueOr)> { + fn extract_kw_value(&mut self, a: &Keyword, v: TypedValueOr) -> Result<(KnownEntid, TypedValueOr)> { let attribute: KnownEntid; if let Some((attr, aa)) = self.in_progress.attribute_for_ident(a) { if let Either::Left(ref tv) = v { @@ -289,12 +289,12 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> { } impl<'a, 'c> EntityBuilder> { - pub fn add_kw(&mut self, a: &NamespacedKeyword, v: V) -> Result<()> + pub fn add_kw(&mut self, a: &Keyword, v: V) -> Result<()> where V: IntoThing> { self.builder.add_kw(self.entity.clone(), a, v) } - pub fn retract_kw(&mut self, a: &NamespacedKeyword, v: V) -> Result<()> + pub fn retract_kw(&mut self, a: &Keyword, v: V) -> Result<()> where V: IntoThing> { self.builder.retract_kw(self.entity.clone(), a, v) } diff --git a/src/errors.rs b/src/errors.rs index 679388fd..bcf340c6 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -95,7 +95,7 @@ error_chain! { display("core schema: wanted {}, got {:?}", mentat_db::CORE_SCHEMA_VERSION, version) } - MissingCoreVocabulary(kw: mentat_query::NamespacedKeyword) { + MissingCoreVocabulary(kw: mentat_query::Keyword) { description("missing core vocabulary") display("missing core attribute {}", kw) } diff --git a/src/lib.rs b/src/lib.rs index 79029994..029ad1e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ pub use mentat_core::{ DateTime, HasSchema, KnownEntid, - NamespacedKeyword, + Keyword, Schema, Binding, TypedValue, @@ -70,25 +70,29 @@ macro_rules! var { }; } -/// Produce the appropriate `NamespacedKeyword` for the provided namespace and name. +/// Produce the appropriate `Keyword` for the provided namespace and name. /// This lives here because we can't re-export macros: /// https://github.com/rust-lang/rust/issues/29638. #[macro_export] macro_rules! kw { + ( : $n:ident ) => { + $crate::Keyword::plain( + stringify!($n) + ) + }; + ( : $ns:ident / $n:ident ) => { - // We don't need to go through `new` -- `ident` is strict enough. - $crate::NamespacedKeyword { - namespace: stringify!($ns).into(), - name: stringify!($n).into(), - } + $crate::Keyword::namespaced( + stringify!($ns), + stringify!($n) + ) }; ( : $ns:ident$(. $nss:ident)+ / $n:ident ) => { - // We don't need to go through `new` -- `ident` is strict enough. - $crate::NamespacedKeyword { - namespace: concat!(stringify!($ns) $(, ".", stringify!($nss))+).into(), - name: stringify!($n).into(), - } + $crate::Keyword::namespaced( + concat!(stringify!($ns) $(, ".", stringify!($nss))+), + stringify!($n) + ) }; } @@ -137,13 +141,13 @@ mod tests { #[test] fn can_import_edn() { - assert_eq!("foo", Keyword::new("foo").0); + assert_eq!(":foo", &Keyword::plain("foo").to_string()); } #[test] fn test_kw() { - assert_eq!(kw!(:foo/bar), NamespacedKeyword::new("foo", "bar")); - assert_eq!(kw!(:org.mozilla.foo/bar_baz), NamespacedKeyword::new("org.mozilla.foo", "bar_baz")); + assert_eq!(kw!(:foo/bar), Keyword::namespaced("foo", "bar")); + assert_eq!(kw!(:org.mozilla.foo/bar_baz), Keyword::namespaced("org.mozilla.foo", "bar_baz")); } #[test] diff --git a/src/query.rs b/src/query.rs index 384ef99e..a0cbd2f8 100644 --- a/src/query.rs +++ b/src/query.rs @@ -33,7 +33,7 @@ pub use mentat_query_algebrizer::{ }; pub use mentat_query::{ - NamespacedKeyword, + Keyword, PlainSymbol, Variable, }; @@ -212,9 +212,9 @@ fn fetch_values<'sqlite> run_algebrized_query(known, sqlite, algebrized) } -fn lookup_attribute(schema: &Schema, attribute: &NamespacedKeyword) -> Result { +fn lookup_attribute(schema: &Schema, attribute: &Keyword) -> Result { schema.get_entid(attribute) - .ok_or_else(|| ErrorKind::UnknownAttribute(attribute.name.clone()).into()) + .ok_or_else(|| ErrorKind::UnknownAttribute(attribute.name().into()).into()) } /// Return a single value for the provided entity and attribute. @@ -271,7 +271,7 @@ pub fn lookup_value_for_attribute<'sqlite, 'attribute, E> (sqlite: &'sqlite rusqlite::Connection, known: Known, entity: E, - attribute: &'attribute NamespacedKeyword) -> Result> + attribute: &'attribute Keyword) -> Result> where E: Into { let attribute = lookup_attribute(known.schema, attribute)?; lookup_value(sqlite, known, entity.into(), attribute) @@ -281,7 +281,7 @@ pub fn lookup_values_for_attribute<'sqlite, 'attribute, E> (sqlite: &'sqlite rusqlite::Connection, known: Known, entity: E, - attribute: &'attribute NamespacedKeyword) -> Result> + attribute: &'attribute Keyword) -> Result> where E: Into { let attribute = lookup_attribute(known.schema, attribute)?; lookup_values(sqlite, known, entity.into(), attribute) diff --git a/src/query_builder.rs b/src/query_builder.rs index 40142b4b..2d998eb7 100644 --- a/src/query_builder.rs +++ b/src/query_builder.rs @@ -15,7 +15,7 @@ use std::collections::{ use mentat_core::{ Entid, - NamespacedKeyword, + Keyword, Binding, TypedValue, ValueType, @@ -53,7 +53,7 @@ impl<'a> QueryBuilder<'a> { self } - pub fn bind_ref_from_kw(&mut self, var: &str, value: NamespacedKeyword) -> Result<&mut Self> { + pub fn bind_ref_from_kw(&mut self, var: &str, value: Keyword) -> Result<&mut Self> { let entid = self.store.conn().current_schema().get_entid(&value).ok_or(ErrorKind::UnknownAttribute(value.to_string()))?; self.values.insert(Variable::from_valid_name(var), TypedValue::Ref(entid.into())); Ok(self) diff --git a/src/vocabulary.rs b/src/vocabulary.rs index 883649f5..f17a3812 100644 --- a/src/vocabulary.rs +++ b/src/vocabulary.rs @@ -109,7 +109,7 @@ use ::{ Entid, HasSchema, IntoResult, - NamespacedKeyword, + Keyword, Binding, TypedValue, ValueType, @@ -157,9 +157,9 @@ pub type Datom = (Entid, Entid, TypedValue); /// checks or employ more fine-grained logic. #[derive(Clone)] pub struct Definition { - pub name: NamespacedKeyword, + pub name: Keyword, pub version: Version, - pub attributes: Vec<(NamespacedKeyword, Attribute)>, + pub attributes: Vec<(Keyword, Attribute)>, pub pre: fn(&mut InProgress, &Vocabulary) -> Result<()>, pub post: fn(&mut InProgress, &Vocabulary) -> Result<()>, } @@ -252,8 +252,8 @@ impl Definition { } pub fn new(name: N, version: Version, attributes: A) -> Definition - where N: Into, - A: Into> { + where N: Into, + A: Into> { Definition { name: name.into(), version: version, @@ -279,7 +279,7 @@ impl Definition { /// A definition of a vocabulary as retrieved from a particular store. /// /// A `Vocabulary` is just like `Definition`, but concrete: its name and attributes are identified -/// by `Entid`, not `NamespacedKeyword`. +/// by `Entid`, not `Keyword`. #[derive(Clone, Debug, Eq, PartialEq)] pub struct Vocabulary { pub entity: Entid, @@ -295,68 +295,68 @@ impl Vocabulary { /// A collection of named `Vocabulary` instances, as retrieved from the store. #[derive(Debug, Default, Clone)] -pub struct Vocabularies(pub BTreeMap); // N.B., this has a copy of the attributes in Schema! +pub struct Vocabularies(pub BTreeMap); // N.B., this has a copy of the attributes in Schema! impl Vocabularies { pub fn len(&self) -> usize { self.0.len() } - pub fn get(&self, name: &NamespacedKeyword) -> Option<&Vocabulary> { + pub fn get(&self, name: &Keyword) -> Option<&Vocabulary> { self.0.get(name) } - pub fn iter(&self) -> ::std::collections::btree_map::Iter { + pub fn iter(&self) -> ::std::collections::btree_map::Iter { self.0.iter() } } lazy_static! { - static ref DB_SCHEMA_CORE: NamespacedKeyword = { + static ref DB_SCHEMA_CORE: Keyword = { kw!(:db.schema/core) }; - static ref DB_SCHEMA_ATTRIBUTE: NamespacedKeyword = { + static ref DB_SCHEMA_ATTRIBUTE: Keyword = { kw!(:db.schema/attribute) }; - static ref DB_SCHEMA_VERSION: NamespacedKeyword = { + static ref DB_SCHEMA_VERSION: Keyword = { kw!(:db.schema/version) }; - static ref DB_IDENT: NamespacedKeyword = { + static ref DB_IDENT: Keyword = { kw!(:db/ident) }; - static ref DB_UNIQUE: NamespacedKeyword = { + static ref DB_UNIQUE: Keyword = { kw!(:db/unique) }; - static ref DB_UNIQUE_VALUE: NamespacedKeyword = { + static ref DB_UNIQUE_VALUE: Keyword = { kw!(:db.unique/value) }; - static ref DB_UNIQUE_IDENTITY: NamespacedKeyword = { + static ref DB_UNIQUE_IDENTITY: Keyword = { kw!(:db.unique/identity) }; - static ref DB_IS_COMPONENT: NamespacedKeyword = { - NamespacedKeyword::new("db", "isComponent") + static ref DB_IS_COMPONENT: Keyword = { + Keyword::namespaced("db", "isComponent") }; - static ref DB_VALUE_TYPE: NamespacedKeyword = { - NamespacedKeyword::new("db", "valueType") + static ref DB_VALUE_TYPE: Keyword = { + Keyword::namespaced("db", "valueType") }; - static ref DB_INDEX: NamespacedKeyword = { + static ref DB_INDEX: Keyword = { kw!(:db/index) }; - static ref DB_FULLTEXT: NamespacedKeyword = { + static ref DB_FULLTEXT: Keyword = { kw!(:db/fulltext) }; - static ref DB_CARDINALITY: NamespacedKeyword = { + static ref DB_CARDINALITY: Keyword = { kw!(:db/cardinality) }; - static ref DB_CARDINALITY_ONE: NamespacedKeyword = { + static ref DB_CARDINALITY_ONE: Keyword = { kw!(:db.cardinality/one) }; - static ref DB_CARDINALITY_MANY: NamespacedKeyword = { + static ref DB_CARDINALITY_MANY: Keyword = { kw!(:db.cardinality/many) }; - static ref DB_NO_HISTORY: NamespacedKeyword = { - NamespacedKeyword::new("db", "noHistory") + static ref DB_NO_HISTORY: Keyword = { + Keyword::namespaced("db", "noHistory") }; } @@ -365,11 +365,11 @@ trait HasCoreSchema { fn core_type(&self, t: ValueType) -> Result; /// Return the entity ID for an ident. On failure, return `MissingCoreVocabulary`. - fn core_entid(&self, ident: &NamespacedKeyword) -> Result; + fn core_entid(&self, ident: &Keyword) -> Result; /// Return the entity ID for an attribute's keyword. On failure, return /// `MissingCoreVocabulary`. - fn core_attribute(&self, ident: &NamespacedKeyword) -> Result; + fn core_attribute(&self, ident: &Keyword) -> Result; } impl HasCoreSchema for T where T: HasSchema { @@ -378,12 +378,12 @@ impl HasCoreSchema for T where T: HasSchema { .ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into()) } - fn core_entid(&self, ident: &NamespacedKeyword) -> Result { + fn core_entid(&self, ident: &Keyword) -> Result { self.get_entid(ident) .ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into()) } - fn core_attribute(&self, ident: &NamespacedKeyword) -> Result { + fn core_attribute(&self, ident: &Keyword) -> Result { self.attribute_for_ident(ident) .ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into()) .map(|(_, e)| e) @@ -391,9 +391,9 @@ impl HasCoreSchema for T where T: HasSchema { } impl Definition { - fn description_for_attributes<'s, T, R>(&'s self, attributes: &[R], via: &T, diff: Option>) -> Result + fn description_for_attributes<'s, T, R>(&'s self, attributes: &[R], via: &T, diff: Option>) -> Result where T: HasCoreSchema, - R: ::std::borrow::Borrow<(NamespacedKeyword, Attribute)> { + R: ::std::borrow::Borrow<(Keyword, Attribute)> { // The attributes we'll need to describe this vocabulary. let a_version = via.core_attribute(&DB_SCHEMA_VERSION)?; @@ -520,7 +520,7 @@ pub enum VocabularyCheck<'definition> { PresentButTooNew { newer_version: Vocabulary }, /// The provided definition is present in the store, but some of its attributes are not. - PresentButMissingAttributes { attributes: Vec<&'definition (NamespacedKeyword, Attribute)> }, + PresentButMissingAttributes { attributes: Vec<&'definition (Keyword, Attribute)> }, } /// This enum captures the outcome of attempting to ensure that a vocabulary definition is present @@ -545,7 +545,7 @@ pub enum VocabularyOutcome { /// This trait captures the ability to retrieve and describe stored vocabularies. pub trait HasVocabularies { fn read_vocabularies(&self) -> Result; - fn read_vocabulary_named(&self, name: &NamespacedKeyword) -> Result>; + fn read_vocabulary_named(&self, name: &Keyword) -> Result>; } /// This trait captures the ability of a store to check and install/upgrade vocabularies. @@ -557,7 +557,7 @@ pub trait VersionedStore: HasVocabularies + HasSchema { // Check the version. if vocabulary.version == definition.version { // Same version. Check that all of our attributes are present. - let mut missing: Vec<&'definition (NamespacedKeyword, Attribute)> = vec![]; + let mut missing: Vec<&'definition (Keyword, Attribute)> = vec![]; for pair in definition.attributes.iter() { if let Some(entid) = self.get_entid(&pair.0) { if let Some(existing) = vocabulary.find(entid) { @@ -609,7 +609,7 @@ pub trait VersionedStore: HasVocabularies + HasSchema { /// /// Use this function instead of calling `ensure_vocabulary` if you need to have pre/post /// functions invoked when vocabulary changes are necessary. - fn ensure_vocabularies(&mut self, vocabularies: &mut VocabularySource) -> Result>; + fn ensure_vocabularies(&mut self, vocabularies: &mut VocabularySource) -> Result>; /// Make sure that our expectations of the core vocabulary — basic types and attributes — are met. fn verify_core_schema(&self) -> Result<()> { @@ -632,13 +632,13 @@ pub trait VersionedStore: HasVocabularies + HasSchema { /// vocabularies — you can retrieve the requested definition and the resulting `VocabularyCheck` /// by name. pub trait VocabularyStatus { - fn get(&self, name: &NamespacedKeyword) -> Option<(&Definition, &VocabularyCheck)>; - fn version(&self, name: &NamespacedKeyword) -> Option; + fn get(&self, name: &Keyword) -> Option<(&Definition, &VocabularyCheck)>; + fn version(&self, name: &Keyword) -> Option; } #[derive(Default)] struct CheckedVocabularies<'a> { - items: BTreeMap)>, + items: BTreeMap)>, } impl<'a> CheckedVocabularies<'a> { @@ -652,18 +652,18 @@ impl<'a> CheckedVocabularies<'a> { } impl<'a> VocabularyStatus for CheckedVocabularies<'a> { - fn get(&self, name: &NamespacedKeyword) -> Option<(&Definition, &VocabularyCheck)> { + fn get(&self, name: &Keyword) -> Option<(&Definition, &VocabularyCheck)> { self.items.get(name).map(|&(ref d, ref c)| (*d, c)) } - fn version(&self, name: &NamespacedKeyword) -> Option { + fn version(&self, name: &Keyword) -> Option { self.items.get(name).map(|&(d, _)| d.version) } } trait VocabularyMechanics { fn install_vocabulary(&mut self, definition: &Definition) -> Result; - fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (NamespacedKeyword, Attribute)>) -> Result; + fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (Keyword, Attribute)>) -> Result; fn upgrade_vocabulary(&mut self, definition: &Definition, from_version: Vocabulary) -> Result; } @@ -686,7 +686,7 @@ impl<'a, 'c> VersionedStore for InProgress<'a, 'c> { } } - fn ensure_vocabularies(&mut self, vocabularies: &mut VocabularySource) -> Result> { + fn ensure_vocabularies(&mut self, vocabularies: &mut VocabularySource) -> Result> { let definitions = vocabularies.definitions(); let mut update = Vec::new(); @@ -817,7 +817,7 @@ impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> { Ok(VocabularyOutcome::Installed) } - fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (NamespacedKeyword, Attribute)>) -> Result { + fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (Keyword, Attribute)>) -> Result { let (terms, tempids) = definition.description_for_attributes(&attributes, self, None)?; self.transact_terms(terms, tempids)?; Ok(VocabularyOutcome::InstalledMissingAttributes) @@ -843,7 +843,7 @@ impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> { } impl HasVocabularies for T where T: HasSchema + Queryable { - fn read_vocabulary_named(&self, name: &NamespacedKeyword) -> Result> { + fn read_vocabulary_named(&self, name: &Keyword) -> Result> { if let Some(entid) = self.get_entid(name) { match self.lookup_value_for_attribute(entid, &DB_SCHEMA_VERSION)? { None => Ok(None), diff --git a/tests/pull.rs b/tests/pull.rs index dda56c10..e8eb6468 100644 --- a/tests/pull.rs +++ b/tests/pull.rs @@ -34,7 +34,7 @@ use mentat::{ Entid, HasSchema, IntoResult, - NamespacedKeyword, + Keyword, Pullable, Queryable, QueryInputs, @@ -127,14 +127,14 @@ fn test_simple_pull() { .into_rel_result() .expect("results"); - let beacon_district: Vec<(NamespacedKeyword, TypedValue)> = vec![ + let beacon_district: Vec<(Keyword, TypedValue)> = vec![ (kw!(:district/name), "Greater Duwamish".into()), - (kw!(:district/region), schema.get_entid(&NamespacedKeyword::new("region", "se")).unwrap().into()) + (kw!(:district/region), schema.get_entid(&Keyword::namespaced("region", "se")).unwrap().into()) ]; let beacon_district: StructuredMap = beacon_district.into(); - let capitol_district: Vec<(NamespacedKeyword, TypedValue)> = vec![ + let capitol_district: Vec<(Keyword, TypedValue)> = vec![ (kw!(:district/name), "East".into()), - (kw!(:district/region), schema.get_entid(&NamespacedKeyword::new("region", "e")).unwrap().into()) + (kw!(:district/region), schema.get_entid(&Keyword::namespaced("region", "e")).unwrap().into()) ]; let capitol_district: StructuredMap = capitol_district.into(); diff --git a/tests/query.rs b/tests/query.rs index 8a981bc8..3cdb72c9 100644 --- a/tests/query.rs +++ b/tests/query.rs @@ -42,7 +42,7 @@ use mentat_query_projector::{ use mentat::{ IntoResult, - NamespacedKeyword, + Keyword, PlainSymbol, QueryInputs, Queryable, @@ -135,7 +135,7 @@ fn test_scalar() { if let QueryResults::Scalar(Some(Binding::Scalar(TypedValue::Keyword(ref rc)))) = results { // Should be '24'. - assert_eq!(&NamespacedKeyword::new("db.type", "keyword"), rc.as_ref()); + assert_eq!(&Keyword::namespaced("db.type", "keyword"), rc.as_ref()); assert_eq!(KnownEntid(24), db.schema.get_entid(rc).unwrap()); } else { @@ -165,7 +165,7 @@ fn test_tuple() { assert_eq!(1, results.len()); if let QueryResults::Tuple(Some(ref tuple)) = results { - let cardinality_one = NamespacedKeyword::new("db.cardinality", "one"); + let cardinality_one = Keyword::namespaced("db.cardinality", "one"); assert_eq!(tuple.len(), 2); assert_eq!(tuple[0], TypedValue::Boolean(true).into()); assert_eq!(tuple[1], db.schema.get_entid(&cardinality_one).expect("c1").into()); @@ -216,7 +216,7 @@ fn test_inputs() { .results; if let QueryResults::Scalar(Some(Binding::Scalar(TypedValue::Keyword(value)))) = results { - assert_eq!(value.as_ref(), &NamespacedKeyword::new("db.install", "valueType")); + assert_eq!(value.as_ref(), &Keyword::namespaced("db.install", "valueType")); } else { panic!("Expected scalar."); } diff --git a/tests/vocabulary.rs b/tests/vocabulary.rs index a0ecc538..46dd4c1f 100644 --- a/tests/vocabulary.rs +++ b/tests/vocabulary.rs @@ -44,7 +44,7 @@ use mentat::{ Conn, InProgress, KnownEntid, - NamespacedKeyword, + Keyword, QueryInputs, Queryable, RelResult, @@ -65,11 +65,11 @@ use mentat::errors::{ }; lazy_static! { - static ref FOO_NAME: NamespacedKeyword = { + static ref FOO_NAME: Keyword = { kw!(:foo/name) }; - static ref FOO_MOMENT: NamespacedKeyword = { + static ref FOO_MOMENT: Keyword = { kw!(:foo/moment) }; diff --git a/tools/cli/src/mentat_cli/repl.rs b/tools/cli/src/mentat_cli/repl.rs index db88881a..f6a47c09 100644 --- a/tools/cli/src/mentat_cli/repl.rs +++ b/tools/cli/src/mentat_cli/repl.rs @@ -29,7 +29,7 @@ use mentat_core::{ use mentat::{ CacheDirection, - NamespacedKeyword, + Keyword, Queryable, QueryExplanation, QueryOutput, @@ -109,12 +109,12 @@ fn eprint_out(s: &str) { eprint!("{green}{s}{reset}", green = color::Fg(::GREEN), s = s, reset = color::Fg(color::Reset)); } -fn parse_namespaced_keyword(input: &str) -> Option { +fn parse_namespaced_keyword(input: &str) -> Option { let splits = [':', '/']; let mut i = input.split(&splits[..]); match (i.next(), i.next(), i.next(), i.next()) { (Some(""), Some(namespace), Some(name), None) => { - Some(NamespacedKeyword::new(namespace, name)) + Some(Keyword::namespaced(namespace, name)) }, _ => None, }