From d49f7025125dd3f023e0fcd87ee90dd02d1df025 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Mon, 18 Jun 2018 11:05:35 -0700 Subject: [PATCH] Part 1: Expand Binding::val() into Binding::{into_*,as_*}. This is simply for completeness: we should provide fundamental conversion patterns even when they are mostly unused in our code base. --- core/src/types.rs | 105 +++++++++++++++++++++++++++++++++++++++++--- src/query.rs | 4 +- src/store.rs | 4 +- src/vocabulary.rs | 2 +- tests/pull.rs | 2 +- tests/vocabulary.rs | 2 +- 6 files changed, 107 insertions(+), 12 deletions(-) diff --git a/core/src/types.rs b/core/src/types.rs index 992ddb38..7efc26f2 100644 --- a/core/src/types.rs +++ b/core/src/types.rs @@ -8,6 +8,10 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. +use ::std::convert::{ + AsRef, +}; + use ::std::ffi::{ CString, }; @@ -282,12 +286,47 @@ impl From> for Binding { } impl Binding { - pub fn val(self) -> Option { + pub fn into_scalar(self) -> Option { match self { Binding::Scalar(v) => Some(v), _ => None, } } + + pub fn into_vec(self) -> Option>> { + match self { + Binding::Vec(v) => Some(v), + _ => None, + } + } + + pub fn into_map(self) -> Option> { + match self { + Binding::Map(v) => Some(v), + _ => None, + } + } + + pub fn as_scalar(&self) -> Option<&TypedValue> { + match self { + &Binding::Scalar(ref v) => Some(v), + _ => None, + } + } + + pub fn as_vec(&self) -> Option<&Vec> { + match self { + &Binding::Vec(ref v) => Some(v), + _ => None, + } + } + + pub fn as_map(&self) -> Option<&StructuredMap> { + match self { + &Binding::Map(ref v) => Some(v), + _ => None, + } + } } /// A pull expression expands a binding into a structure. The returned structure @@ -379,15 +418,15 @@ impl TypedValue { /// Construct a new `TypedValue::Keyword` instance by cloning the provided /// 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 { - Keyword::namespaced(ns, name).into() + pub fn typed_ns_keyword, T: AsRef>(ns: S, name: T) -> TypedValue { + Keyword::namespaced(ns.as_ref(), name.as_ref()).into() } /// Construct a new `TypedValue::String` instance by cloning the provided /// value and wrapping it in a new `ValueRc`. This is expensive, so this might /// be best limited to tests. - pub fn typed_string(s: &str) -> TypedValue { - s.into() + pub fn typed_string>(s: S) -> TypedValue { + s.as_ref().into() } pub fn current_instant() -> TypedValue { @@ -736,6 +775,62 @@ impl Binding { _ => None, } } + + pub fn as_entid(&self) -> Option<&Entid> { + match self { + &Binding::Scalar(TypedValue::Ref(ref v)) => Some(v), + _ => None, + } + } + + pub fn as_kw(&self) -> Option<&ValueRc> { + match self { + &Binding::Scalar(TypedValue::Keyword(ref v)) => Some(v), + _ => None, + } + } + + pub fn as_boolean(&self) -> Option<&bool> { + match self { + &Binding::Scalar(TypedValue::Boolean(ref v)) => Some(v), + _ => None, + } + } + + pub fn as_long(&self) -> Option<&i64> { + match self { + &Binding::Scalar(TypedValue::Long(ref v)) => Some(v), + _ => None, + } + } + + pub fn as_double(&self) -> Option<&f64> { + match self { + &Binding::Scalar(TypedValue::Double(ref v)) => Some(&v.0), + _ => None, + } + } + + pub fn as_instant(&self) -> Option<&DateTime> { + match self { + &Binding::Scalar(TypedValue::Instant(ref v)) => Some(v), + _ => None, + } + } + + pub fn as_string(&self) -> Option<&ValueRc> { + match self { + &Binding::Scalar(TypedValue::String(ref v)) => Some(v), + _ => None, + } + } + + pub fn as_uuid(&self) -> Option<&Uuid> { + match self { + &Binding::Scalar(TypedValue::Uuid(ref v)) => Some(v), + _ => None, + } + } } #[test] diff --git a/src/query.rs b/src/query.rs index 16fa3e3f..a4f4a979 100644 --- a/src/query.rs +++ b/src/query.rs @@ -234,7 +234,7 @@ pub fn lookup_value<'sqlite, 'schema, 'cache, E, A> fetch_values(sqlite, known, entid, attrid, true) .into_scalar_result() // Safe to unwrap: we never retrieve structure. - .map(|r| r.map(|v| v.val().unwrap())) + .map(|r| r.map(|v| v.into_scalar().unwrap())) } } @@ -256,7 +256,7 @@ pub fn lookup_values<'sqlite, E, A> fetch_values(sqlite, known, entid, attrid, false) .into_coll_result() // Safe to unwrap: we never retrieve structure. - .map(|v| v.into_iter().map(|x| x.val().unwrap()).collect()) + .map(|v| v.into_iter().map(|x| x.into_scalar().unwrap()).collect()) } } diff --git a/src/store.rs b/src/store.rs index 1cfce8bc..1614d0f5 100644 --- a/src/store.rs +++ b/src/store.rs @@ -609,7 +609,7 @@ mod tests { let mut builder = in_progress.builder().describe_tempid(&name); builder.add(kw!(:todo/uuid), TypedValue::Uuid(uuid)).expect("Expected added uuid"); changeset.insert(uuid_entid.clone()); - builder.add(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!(:todo/completion_date), TypedValue::current_instant()).expect("Expected added date"); @@ -678,7 +678,7 @@ mod tests { for i in 0..3 { let name = format!("label{}", i); let mut builder = in_progress.builder().describe_tempid(&name); - builder.add(kw!(:label/name), TypedValue::typed_string(&name)).expect("Expected added name"); + 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 42674b5b..b3cb6f24 100644 --- a/src/vocabulary.rs +++ b/src/vocabulary.rs @@ -227,7 +227,7 @@ pub struct Definition { /// for row in results.into_iter() { /// let mut r = row.into_iter(); /// let e = r.next().and_then(|e| e.into_known_entid()).expect("entity"); -/// let obsolete = r.next().expect("value").val().expect("typed value"); +/// let obsolete = r.next().expect("value").into_scalar().expect("typed value"); /// builder.retract(e, link_title, obsolete)?; /// } /// ip.transact_builder(builder)?; diff --git a/tests/pull.rs b/tests/pull.rs index a2c21f91..ba8a7570 100644 --- a/tests/pull.rs +++ b/tests/pull.rs @@ -86,7 +86,7 @@ fn test_simple_pull() { .expect("hoods") .into_iter() .map(|b| { - b.val().and_then(|tv| tv.into_entid()).expect("scalar") + b.into_scalar().and_then(|tv| tv.into_entid()).expect("scalar") }) .collect(); diff --git a/tests/vocabulary.rs b/tests/vocabulary.rs index e8f7ce5d..f5905a94 100644 --- a/tests/vocabulary.rs +++ b/tests/vocabulary.rs @@ -350,7 +350,7 @@ fn av(row: Vec) -> (KnownEntid, TypedValue) { let mut row = row.into_iter(); match (row.next(), row.next()) { (Some(Binding::Scalar(TypedValue::Ref(a))), Some(v)) => { - (KnownEntid(a), v.val().unwrap()) + (KnownEntid(a), v.into_scalar().unwrap()) }, _ => panic!("Incorrect query shape for 'av' helper."), }