From 1cb1847aa6c2e021ef43e0a7b1ea0c8f8e2a49f3 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Tue, 3 Jul 2018 12:45:02 -0700 Subject: [PATCH] Part 5: Make existing `TermBuilder` actually build `Entity` instances. There are a few tricky details to call out here. The first is the `TransactableValueMarker` trait. This is strictly a marker (like `Sized`, for example) to give some control over what types can be used as value types in `Entity` instances. This expression is needed due to the network of `Into` and `From` relations between the parts of valid `Entity` instances. This allows to drop the `IntoThing` work-around trait and use the established patterns. (Observe that `KnownEntid` makes this a little harder, due to the cross-crate consistency restrictions.) The second is that we can get rid `{add,retract}_kw`, since the network of relations expresses the coercions directly. The third is that this commit doesn't change the name `TermBuilder`, even though it is now building `Entity` instances. This is because there's _already_ an `EntityBuilder` which fixes the `EntityPlace`. It's not clear whether the existing entity building interface should be removed or whether both should be renamed. That can be follow-up. --- core/src/types.rs | 29 ++++++ edn/src/entities.rs | 110 ++++++++++++++++++++ ffi/src/lib.rs | 69 +++++++------ src/conn.rs | 4 +- src/entity_builder.rs | 226 +++++++++++------------------------------- src/store.rs | 14 +-- src/vocabulary.rs | 12 +-- 7 files changed, 246 insertions(+), 218 deletions(-) diff --git a/core/src/types.rs b/core/src/types.rs index 716f943f..992ddb38 100644 --- a/core/src/types.rs +++ b/core/src/types.rs @@ -47,6 +47,14 @@ use ::edn::{ ValueRc, }; +use ::edn::entities::{ + AttributePlace, + EntidOrIdent, + EntityPlace, + ValuePlace, + TransactableValueMarker, +}; + use values; /// Represents one entid in the entid space. @@ -73,6 +81,24 @@ impl From for TypedValue { } } +impl Into> for KnownEntid { + fn into(self) -> EntityPlace { + EntityPlace::Entid(EntidOrIdent::Entid(self.0)) + } +} + +impl Into for KnownEntid { + fn into(self) -> AttributePlace { + AttributePlace::Entid(EntidOrIdent::Entid(self.0)) + } +} + +impl Into> for KnownEntid { + fn into(self) -> ValuePlace { + ValuePlace::Entid(EntidOrIdent::Entid(self.0)) + } +} + /// The attribute of each Mentat assertion has a :db/valueType constraining the value to a /// particular set. Mentat recognizes the following :db/valueType values. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] @@ -215,6 +241,9 @@ pub enum TypedValue { Uuid(Uuid), // It's only 128 bits, so this should be acceptable to clone. } +/// `TypedValue` is the value type for programmatic use in transaction builders. +impl TransactableValueMarker for TypedValue {} + /// The values bound in a query specification can be: /// /// * Vecs of structured values, for multi-valued component attributes or nested expressions. diff --git a/edn/src/entities.rs b/edn/src/entities.rs index 1ddb4552..c6c27704 100644 --- a/edn/src/entities.rs +++ b/edn/src/entities.rs @@ -22,6 +22,20 @@ use symbols::{ PlainSymbol, }; +use types::{ + ValueAndSpan, +}; + +/// `EntityPlace` and `ValuePlace` embed values, either directly (i.e., `ValuePlace::Atom`) or +/// indirectly (i.e., `EntityPlace::LookupRef`). In order to maintain the graph of `Into` and +/// `From` relations, we need to ensure that `{Value,Entity}Place` can't match as a potential value. +/// (If it does, the `impl Into for T` default conflicts.) This marker trait allows to mark +/// acceptable values, thereby removing `{Entity,Value}Place` from consideration. +pub trait TransactableValueMarker {} + +/// `ValueAndSpan` is the value type coming out of the entity parser. +impl TransactableValueMarker for ValueAndSpan {} + /// A tempid, either an external tempid given in a transaction (usually as an `Value::Text`), /// or an internal tempid allocated by Mentat itself. #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] @@ -54,6 +68,18 @@ pub enum EntidOrIdent { Ident(Keyword), } +impl From for EntidOrIdent { + fn from(v: i64) -> Self { + EntidOrIdent::Entid(v) + } +} + +impl From for EntidOrIdent { + fn from(v: Keyword) -> Self { + EntidOrIdent::Ident(v) + } +} + impl EntidOrIdent { pub fn unreversed(&self) -> Option { match self { @@ -105,6 +131,54 @@ pub enum ValuePlace { MapNotation(MapNotation), } +impl From for ValuePlace { + fn from(v: EntidOrIdent) -> Self { + ValuePlace::Entid(v) + } +} + +impl From for ValuePlace { + fn from(v: TempId) -> Self { + ValuePlace::TempId(v.into()) + } +} + +impl From> for ValuePlace { + fn from(v: ValueRc) -> Self { + ValuePlace::TempId(v) + } +} + +impl From> for ValuePlace { + fn from(v: LookupRef) -> Self { + ValuePlace::LookupRef(v) + } +} + +impl From for ValuePlace { + fn from(v: TxFunction) -> Self { + ValuePlace::TxFunction(v) + } +} + +impl From>> for ValuePlace { + fn from(v: Vec>) -> Self { + ValuePlace::Vector(v) + } +} + +impl From for ValuePlace { + fn from(v: V) -> Self { + ValuePlace::Atom(v) + } +} + +impl From> for ValuePlace { + fn from(v: MapNotation) -> Self { + ValuePlace::MapNotation(v) + } +} + #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] pub enum EntityPlace { Entid(EntidOrIdent), @@ -113,11 +187,47 @@ pub enum EntityPlace { TxFunction(TxFunction), } +impl> From for EntityPlace { + fn from(v: E) -> Self { + EntityPlace::Entid(v.into()) + } +} + +impl From for EntityPlace { + fn from(v: TempId) -> Self { + EntityPlace::TempId(v.into()) + } +} + +impl From> for EntityPlace { + fn from(v: ValueRc) -> Self { + EntityPlace::TempId(v) + } +} + +impl From> for EntityPlace { + fn from(v: LookupRef) -> Self { + EntityPlace::LookupRef(v) + } +} + +impl From for EntityPlace { + fn from(v: TxFunction) -> Self { + EntityPlace::TxFunction(v) + } +} + #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] pub enum AttributePlace { Entid(EntidOrIdent), } +impl> From for AttributePlace { + fn from(v: A) -> Self { + AttributePlace::Entid(v.into()) + } +} + #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] pub enum OpType { Add, diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index b08d7d38..98c45d8d 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -120,7 +120,6 @@ pub use mentat::entity_builder::{ BuildTerms, EntityBuilder, InProgressBuilder, - IntoThing, }; pub mod android; @@ -339,7 +338,7 @@ pub unsafe extern "C" fn in_progress_entity_builder_from_temp_id<'m>(in_progress pub unsafe extern "C" fn in_progress_entity_builder_from_entid<'m>(in_progress: *mut InProgress<'m, 'm>, entid: c_longlong) -> *mut EntityBuilder { assert_not_null!(in_progress); let in_progress = Box::from_raw(in_progress); - Box::into_raw(Box::new(in_progress.builder().describe(&KnownEntid(entid)))) + Box::into_raw(Box::new(in_progress.builder().describe(KnownEntid(entid)))) } /// Starts a new transaction and creates a builder using the transaction @@ -392,7 +391,7 @@ pub unsafe extern "C" fn store_entity_builder_from_entid<'a, 'c>(store: *mut Sto assert_not_null!(store); let store = &mut *store; let result = store.begin_transaction().and_then(|in_progress| { - Ok(in_progress.builder().describe(&KnownEntid(entid))) + Ok(in_progress.builder().describe(KnownEntid(entid))) }); translate_result(result, error) } @@ -418,7 +417,7 @@ pub unsafe extern "C" fn in_progress_builder_add_string<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = c_char_to_string(value).into(); - translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.add(KnownEntid(entid), kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -441,7 +440,7 @@ pub unsafe extern "C" fn in_progress_builder_add_long<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::Long(value); - translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.add(KnownEntid(entid), kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -465,7 +464,7 @@ pub unsafe extern "C" fn in_progress_builder_add_ref<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::Ref(value); - translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.add(KnownEntid(entid), kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -490,7 +489,7 @@ pub unsafe extern "C" fn in_progress_builder_add_keyword<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = kw_from_string(c_char_to_string(value)).into(); - translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.add(KnownEntid(entid), kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -514,7 +513,7 @@ pub unsafe extern "C" fn in_progress_builder_add_boolean<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = value.into(); - translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.add(KnownEntid(entid), kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -538,7 +537,7 @@ pub unsafe extern "C" fn in_progress_builder_add_double<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = value.into(); - translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.add(KnownEntid(entid), kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -562,7 +561,7 @@ pub unsafe extern "C" fn in_progress_builder_add_timestamp<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::instant(value); - translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.add(KnownEntid(entid), kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -588,7 +587,7 @@ pub unsafe extern "C" fn in_progress_builder_add_uuid<'a, 'c>( let value = &*value; let value = Uuid::from_bytes(value).expect("valid uuid"); let value: TypedValue = value.into(); - translate_void_result(builder.add_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.add(KnownEntid(entid), kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -612,7 +611,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_string<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = c_char_to_string(value).into(); - translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.retract(KnownEntid(entid), kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -636,7 +635,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_long<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::Long(value); - translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.retract(KnownEntid(entid), kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -660,7 +659,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_ref<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::Ref(value); - translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.retract(KnownEntid(entid), kw, value), error); } @@ -685,7 +684,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_keyword<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = kw_from_string(c_char_to_string(value)).into(); - translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.retract(KnownEntid(entid), kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -709,7 +708,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_boolean<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = value.into(); - translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.retract(KnownEntid(entid), kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -733,7 +732,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_double<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = value.into(); - translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.retract(KnownEntid(entid), kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -757,7 +756,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_timestamp<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::instant(value); - translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.retract(KnownEntid(entid), kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -785,7 +784,7 @@ pub unsafe extern "C" fn in_progress_builder_retract_uuid<'a, 'c>( let value = &*value; let value = Uuid::from_bytes(value).expect("valid uuid"); let value: TypedValue = value.into(); - translate_void_result(builder.retract_kw(KnownEntid(entid), &kw, value), error); + translate_void_result(builder.retract(KnownEntid(entid), kw, value), error); } /// Transacts and commits all the assertions and retractions that have been performed @@ -842,7 +841,7 @@ pub unsafe extern "C" fn entity_builder_add_string<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = c_char_to_string(value).into(); - translate_void_result(builder.add_kw(&kw, value), error); + translate_void_result(builder.add(kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -865,7 +864,7 @@ pub unsafe extern "C" fn entity_builder_add_long<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::Long(value); - translate_void_result(builder.add_kw(&kw, value), error); + translate_void_result(builder.add(kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -888,7 +887,7 @@ pub unsafe extern "C" fn entity_builder_add_ref<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::Ref(value); - translate_void_result(builder.add_kw(&kw, value), error); + translate_void_result(builder.add(kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -911,7 +910,7 @@ pub unsafe extern "C" fn entity_builder_add_keyword<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = kw_from_string(c_char_to_string(value)).into(); - translate_void_result(builder.add_kw(&kw, value), error); + translate_void_result(builder.add(kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -934,7 +933,7 @@ pub unsafe extern "C" fn entity_builder_add_boolean<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = value.into(); - translate_void_result(builder.add_kw(&kw, value), error); + translate_void_result(builder.add(kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -957,7 +956,7 @@ pub unsafe extern "C" fn entity_builder_add_double<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = value.into(); - translate_void_result(builder.add_kw(&kw, value), error); + translate_void_result(builder.add(kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -980,7 +979,7 @@ pub unsafe extern "C" fn entity_builder_add_timestamp<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::instant(value); - translate_void_result(builder.add_kw(&kw, value), error); + translate_void_result(builder.add(kw, value), error); } /// Uses `builder` to assert `value` for `kw` on entity `entid`. @@ -1005,7 +1004,7 @@ pub unsafe extern "C" fn entity_builder_add_uuid<'a, 'c>( let value = &*value; let value = Uuid::from_bytes(value).expect("valid uuid"); let value: TypedValue = value.into(); - translate_void_result(builder.add_kw(&kw, value), error); + translate_void_result(builder.add(kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -1028,7 +1027,7 @@ pub unsafe extern "C" fn entity_builder_retract_string<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = c_char_to_string(value).into(); - translate_void_result(builder.retract_kw(&kw, value), error); + translate_void_result(builder.retract(kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -1051,7 +1050,7 @@ pub unsafe extern "C" fn entity_builder_retract_long<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::Long(value); - translate_void_result(builder.retract_kw(&kw, value), error); + translate_void_result(builder.retract(kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -1074,7 +1073,7 @@ pub unsafe extern "C" fn entity_builder_retract_ref<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::Ref(value); - translate_void_result(builder.retract_kw(&kw, value), error); + translate_void_result(builder.retract(kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -1097,7 +1096,7 @@ pub unsafe extern "C" fn entity_builder_retract_keyword<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = kw_from_string(c_char_to_string(value)).into(); - translate_void_result(builder.retract_kw(&kw, value), error); + translate_void_result(builder.retract(kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -1120,7 +1119,7 @@ pub unsafe extern "C" fn entity_builder_retract_boolean<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = value.into(); - translate_void_result(builder.retract_kw(&kw, value), error); + translate_void_result(builder.retract(kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -1143,7 +1142,7 @@ pub unsafe extern "C" fn entity_builder_retract_double<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = value.into(); - translate_void_result(builder.retract_kw(&kw, value), error); + translate_void_result(builder.retract(kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -1166,7 +1165,7 @@ pub unsafe extern "C" fn entity_builder_retract_timestamp<'a, 'c>( let builder = &mut *builder; let kw = kw_from_string(c_char_to_string(kw)); let value: TypedValue = TypedValue::instant(value); - translate_void_result(builder.retract_kw(&kw, value), error); + translate_void_result(builder.retract(kw, value), error); } /// Uses `builder` to retract `value` for `kw` on entity `entid`. @@ -1192,7 +1191,7 @@ pub unsafe extern "C" fn entity_builder_retract_uuid<'a, 'c>( let value = &*value; let value = Uuid::from_bytes(value).expect("valid uuid"); let value: TypedValue = value.into(); - translate_void_result(builder.retract_kw(&kw, value), error); + translate_void_result(builder.retract(kw, value), error); } /// Transacts all the assertions and retractions that have been performed diff --git a/src/conn.rs b/src/conn.rs index 9f9e3ddd..05caf746 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -402,8 +402,8 @@ impl<'a, 'c> InProgress<'a, 'c> { /// This exists so you can make your own. pub fn transact_builder(&mut self, builder: TermBuilder) -> Result { builder.build() - .and_then(|(terms, tempid_set)| { - self.transact_terms(terms, tempid_set) + .and_then(|(terms, _tempid_set)| { + self.transact_entities(terms) }) } diff --git a/src/entity_builder.rs b/src/entity_builder.rs index fe2e52ed..62fd43f3 100644 --- a/src/entity_builder.rs +++ b/src/entity_builder.rs @@ -50,73 +50,65 @@ // // The second is to expose a declarative, programmatic builder pattern for constructing entities. // -// We probably need both, but this file provides the latter. Unfortunately, Entity -- the input to -// the transactor -- is intimately tied to EDN and to spanned values. +// We probably need both, but this file provides the latter. use edn::{ InternSet, + ValueRc, }; use edn::entities::{ + AttributePlace, + Entity, + EntityPlace, OpType, TempId, + ValuePlace, }; use mentat_core::{ - HasSchema, - KnownEntid, - Keyword, TypedValue, }; -use mentat_core::util::Either; - use mentat_db::{ TxReport, }; -use mentat_db::internal_types::{ - KnownEntidOr, - TempIdHandle, - Term, - TermWithTempIds, - TypedValueOr, -}; - use conn::{ InProgress, }; use errors::{ - MentatError, Result, }; -pub type Terms = (Vec, InternSet); +pub type Terms = (Vec>, InternSet); pub struct TermBuilder { tempids: InternSet, - terms: Vec, + terms: Vec>, } pub struct EntityBuilder { builder: T, - entity: KnownEntidOr, + entity: EntityPlace, } pub trait BuildTerms where Self: Sized { - fn named_tempid(&mut self, name: String) -> TempIdHandle; + fn named_tempid(&mut self, name: String) -> ValueRc; fn describe_tempid(self, name: &str) -> EntityBuilder; - fn describe(self, entity: E) -> EntityBuilder where E: IntoThing>; - fn add(&mut self, e: E, a: KnownEntid, v: V) -> Result<()> - where E: IntoThing>, - V: IntoThing>; - fn retract(&mut self, e: E, a: KnownEntid, v: V) -> Result<()> - where E: IntoThing>, - V: IntoThing>; + fn describe(self, entity: E) -> EntityBuilder where E: Into>; + fn add(&mut self, e: E, a: A, v: V) -> Result<()> + where E: Into>, + A: Into, + V: Into>; + fn retract(&mut self, e: E, a: A, v: V) -> Result<()> + where E: Into>, + A: Into, + V: Into>; } impl BuildTerms for TermBuilder { - fn named_tempid(&mut self, name: String) -> TempIdHandle { + fn named_tempid(&mut self, name: String) -> ValueRc { self.tempids.intern(TempId::External(name)) } @@ -125,28 +117,26 @@ impl BuildTerms for TermBuilder { self.describe(e) } - fn describe(self, entity: E) -> EntityBuilder where E: IntoThing> { + fn describe(self, entity: E) -> EntityBuilder where E: Into> { EntityBuilder { builder: self, - entity: entity.into_thing(), + entity: entity.into(), } } - fn add(&mut self, e: E, a: KnownEntid, v: V) -> Result<()> - where E: IntoThing>, - V: IntoThing> { - let e = e.into_thing(); - let v = v.into_thing(); - self.terms.push(Term::AddOrRetract(OpType::Add, e, a.into(), v)); + fn add(&mut self, e: E, a: A, v: V) -> Result<()> + where E: Into>, + A: Into, + V: Into> { + self.terms.push(Entity::AddOrRetract { op: OpType::Add, e: e.into(), a: a.into(), v: v.into() }); Ok(()) } - fn retract(&mut self, e: E, a: KnownEntid, v: V) -> Result<()> - where E: IntoThing>, - V: IntoThing> { - let e = e.into_thing(); - let v = v.into_thing(); - self.terms.push(Term::AddOrRetract(OpType::Retract, e, a.into(), v)); + fn retract(&mut self, e: E, a: A, v: V) -> Result<()> + where E: Into>, + A: Into, + V: Into> { + self.terms.push(Entity::AddOrRetract { op: OpType::Retract, e: e.into(), a: a.into(), v: v.into() }); Ok(()) } } @@ -168,23 +158,25 @@ impl TermBuilder { } #[allow(dead_code)] - pub fn numbered_tempid(&mut self, id: i64) -> TempIdHandle { + pub fn numbered_tempid(&mut self, id: i64) -> ValueRc { self.tempids.intern(TempId::Internal(id)) } } impl EntityBuilder where T: BuildTerms { - pub fn finish(self) -> (T, KnownEntidOr) { + pub fn finish(self) -> (T, EntityPlace) { (self.builder, self.entity) } - pub fn add(&mut self, a: KnownEntid, v: V) -> Result<()> - where V: IntoThing> { + pub fn add(&mut self, a: A, v: V) -> Result<()> + where A: Into, + V: Into> { self.builder.add(self.entity.clone(), a, v) } - pub fn retract(&mut self, a: KnownEntid, v: V) -> Result<()> - where V: IntoThing> { + pub fn retract(&mut self, a: A, v: V) -> Result<()> + where A: Into, + V: Into> { self.builder.retract(self.entity.clone(), a, v) } } @@ -209,8 +201,8 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> { let mut in_progress = self.in_progress; let result = self.builder .build() - .and_then(|(terms, tempid_set)| { - in_progress.transact_terms(terms, tempid_set) + .and_then(|(terms, _tempid_set)| { + in_progress.transact_entities(terms) }); (in_progress, result) } @@ -228,7 +220,7 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> { } impl<'a, 'c> BuildTerms for InProgressBuilder<'a, 'c> { - fn named_tempid(&mut self, name: String) -> TempIdHandle { + fn named_tempid(&mut self, name: String) -> ValueRc { self.builder.named_tempid(name) } @@ -237,70 +229,29 @@ impl<'a, 'c> BuildTerms for InProgressBuilder<'a, 'c> { self.describe(e) } - fn describe(self, entity: E) -> EntityBuilder> where E: IntoThing> { + fn describe(self, entity: E) -> EntityBuilder> where E: Into> { EntityBuilder { builder: self, - entity: entity.into_thing(), + entity: entity.into(), } } - fn add(&mut self, e: E, a: KnownEntid, v: V) -> Result<()> - where E: IntoThing>, - V: IntoThing> { + fn add(&mut self, e: E, a: A, v: V) -> Result<()> + where E: Into>, + A: Into, + V: Into> { self.builder.add(e, a, v) } - fn retract(&mut self, e: E, a: KnownEntid, v: V) -> Result<()> - where E: IntoThing>, - V: IntoThing> { + fn retract(&mut self, e: E, a: A, v: V) -> Result<()> + where E: Into>, + A: Into, + V: Into> { self.builder.retract(e, a, v) } } -impl<'a, 'c> InProgressBuilder<'a, 'c> { - 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: &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: &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 { - let provided = tv.value_type(); - let expected = attr.value_type; - if provided != expected { - bail!(MentatError::ValueTypeMismatch(provided, expected)); - } - } - attribute = aa; - } else { - bail!(MentatError::UnknownAttribute(a.to_string())); - } - Ok((attribute, v)) - } -} - impl<'a, 'c> EntityBuilder> { - 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: &Keyword, v: V) -> Result<()> - where V: IntoThing> { - self.builder.retract_kw(self.entity.clone(), a, v) - } - /// Build the terms from this builder and transact them against the current /// `InProgress`. This method _always_ returns the `InProgress` -- failure doesn't /// imply an automatic rollback. @@ -315,69 +266,6 @@ impl<'a, 'c> EntityBuilder> { } } -// Can't implement Into for Rc. -pub trait IntoThing: Sized { - fn into_thing(self) -> T; -} - -pub trait FromThing { - fn from_thing(v: T) -> Self; -} - -impl FromThing for T { - fn from_thing(v: T) -> T { - v - } -} - -impl IntoThing for F where I: FromThing { - fn into_thing(self) -> I { - I::from_thing(self) - } -} - -impl<'a> FromThing<&'a TempIdHandle> for TypedValueOr { - fn from_thing(v: &'a TempIdHandle) -> Self { - Either::Right(v.clone()) - } -} - -impl FromThing for TypedValueOr { - fn from_thing(v: TempIdHandle) -> Self { - Either::Right(v) - } -} - -impl FromThing for TypedValueOr { - fn from_thing(v: TypedValue) -> Self { - Either::Left(v) - } -} - -impl FromThing for KnownEntidOr { - fn from_thing(v: TempIdHandle) -> Self { - Either::Right(v) - } -} - -impl<'a> FromThing<&'a KnownEntid> for KnownEntidOr { - fn from_thing(v: &'a KnownEntid) -> Self { - Either::Left(v.clone()) - } -} - -impl FromThing for KnownEntidOr { - fn from_thing(v: KnownEntid) -> Self { - Either::Left(v) - } -} - -impl FromThing for TypedValueOr { - fn from_thing(v: KnownEntid) -> Self { - Either::Left(v.into()) - } -} - #[cfg(test)] mod testing { extern crate mentat_db; @@ -386,6 +274,8 @@ mod testing { Conn, Entid, HasSchema, + KnownEntid, + MentatError, Queryable, TypedValue, TxReport, @@ -421,7 +311,7 @@ mod testing { let mut in_progress = conn.begin_transaction(&mut sqlite).expect("begun successfully"); // This should fail: unrecognized entid. - match in_progress.transact_terms(terms, tempids).expect_err("expected transact to fail") { + match in_progress.transact_entities(terms).expect_err("expected transact to fail") { MentatError::DbError(e) => { assert_eq!(e.kind(), mentat_db::DbErrorKind::UnrecognizedEntid(999)); }, @@ -456,7 +346,7 @@ mod testing { let e_x = builder.named_tempid("x".into()); let v_many_1 = TypedValue::typed_string("Some text"); let v_many_2 = TypedValue::typed_string("Other text"); - builder.add_kw(e_x.clone(), &kw!(:foo/many), v_many_1).expect("add succeeded"); + builder.add(e_x.clone(), kw!(:foo/many), v_many_1).expect("add succeeded"); builder.add(e_x.clone(), a_many, v_many_2).expect("add succeeded"); builder.commit().expect("commit succeeded"); } @@ -510,7 +400,7 @@ mod testing { assert_eq!(tempids.len(), 2); assert_eq!(terms.len(), 4); - report = in_progress.transact_terms(terms, tempids).expect("add succeeded"); + report = in_progress.transact_entities(terms).expect("add succeeded"); let x = report.tempids.get("x").expect("our tempid has an ID"); let y = report.tempids.get("y").expect("our tempid has an ID"); assert_eq!(in_progress.lookup_value_for_attribute(*y, &foo_ref).expect("lookup succeeded"), diff --git a/src/store.rs b/src/store.rs index 21bad12c..8f04d00c 100644 --- a/src/store.rs +++ b/src/store.rs @@ -607,12 +607,12 @@ mod tests { let name = format!("todo{}", i); let uuid = Uuid::new_v4(); let mut builder = in_progress.builder().describe_tempid(&name); - builder.add_kw(&kw!(:todo/uuid), TypedValue::Uuid(uuid)).expect("Expected added uuid"); + builder.add(kw!(:todo/uuid), TypedValue::Uuid(uuid)).expect("Expected added uuid"); changeset.insert(uuid_entid.clone()); - builder.add_kw(&kw!(:todo/name), TypedValue::typed_string(&name)).expect("Expected added name"); + builder.add(kw!(:todo/name), TypedValue::typed_string(&name)).expect("Expected added name"); changeset.insert(name_entid.clone()); if i % 2 == 0 { - builder.add_kw(&kw!(:todo/completion_date), TypedValue::current_instant()).expect("Expected added date"); + builder.add(kw!(:todo/completion_date), TypedValue::current_instant()).expect("Expected added date"); changeset.insert(date_entid.clone()); } let (ip, r) = builder.transact(); @@ -622,8 +622,8 @@ mod tests { in_progress = ip; } let mut builder = in_progress.builder().describe_tempid("Label"); - builder.add_kw(&kw!(:label/name), TypedValue::typed_string("Label 1")).expect("Expected added name"); - builder.add_kw(&kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color"); + builder.add(kw!(:label/name), TypedValue::typed_string("Label 1")).expect("Expected added name"); + builder.add(kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color"); builder.commit().expect("expect transaction to occur"); } @@ -678,8 +678,8 @@ mod tests { for i in 0..3 { let name = format!("label{}", i); let mut builder = in_progress.builder().describe_tempid(&name); - builder.add_kw(&kw!(:label/name), TypedValue::typed_string(&name)).expect("Expected added name"); - builder.add_kw(&kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color"); + builder.add(kw!(:label/name), TypedValue::typed_string(&name)).expect("Expected added name"); + builder.add(kw!(:label/color), TypedValue::typed_string("blue")).expect("Expected added color"); let (ip, _) = builder.transact(); in_progress = ip; } diff --git a/src/vocabulary.rs b/src/vocabulary.rs index 7e622ee2..42674b5b 100644 --- a/src/vocabulary.rs +++ b/src/vocabulary.rs @@ -812,14 +812,14 @@ impl VocabularySource for SimpleVocabularySource { impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> { /// Turn the vocabulary into datoms, transact them, and on success return the outcome. fn install_vocabulary(&mut self, definition: &Definition) -> Result { - let (terms, tempids) = definition.description(self)?; - self.transact_terms(terms, tempids)?; + let (terms, _tempids) = definition.description(self)?; + self.transact_entities(terms)?; Ok(VocabularyOutcome::Installed) } 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)?; + let (terms, _tempids) = definition.description_for_attributes(&attributes, self, None)?; + self.transact_entities(terms)?; Ok(VocabularyOutcome::InstalledMissingAttributes) } @@ -834,8 +834,8 @@ impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> { // TODO: don't do work for attributes that are unchanged. Here we rely on the transactor // to elide duplicate datoms. - let (terms, tempids) = definition.description_diff(self, &from_version)?; - self.transact_terms(terms, tempids)?; + let (terms, _tempids) = definition.description_diff(self, &from_version)?; + self.transact_entities(terms)?; definition.post(self, &from_version)?; Ok(VocabularyOutcome::Upgraded)