diff --git a/src/db/cnf_transform.rs b/src/db/cnf_transform.rs index 9a517485..8f5ca515 100644 --- a/src/db/cnf_transform.rs +++ b/src/db/cnf_transform.rs @@ -17,6 +17,7 @@ fn do_extract_tables(val: &Value, coll: &mut BTreeSet) { | Value::Int(_) | Value::Float(_) | Value::Uuid(_) + | Value::Bytes(_) | Value::Text(_) => {} Value::List(l) => { for v in l { diff --git a/src/db/eval.rs b/src/db/eval.rs index dcab9bc1..19a9be6e 100644 --- a/src/db/eval.rs +++ b/src/db/eval.rs @@ -60,6 +60,7 @@ pub fn tuple_eval<'a>(value: &'a Value<'a>, tuples: &'a MegaTuple) -> Result v.clone(), Value::List(l) => { let l = l @@ -541,6 +542,7 @@ impl<'s> Session<'s> { | Value::Int(_) | Value::Float(_) | Value::Uuid(_) + | Value::Bytes(_) | Value::Text(_) | Value::EndSentinel) => Ok((true, v)), v @ Value::TupleRef(_, _) => Ok((false, v)), @@ -1119,6 +1121,7 @@ impl<'s> Session<'s> { | Value::Float(_) | Value::Uuid(_) | Value::EndSentinel + | Value::Bytes(_) | Value::Text(_) => unreachable!(), Value::List(_) | Value::Dict(_) => { Err(Err(CozoError::InvalidArgument)) @@ -1289,6 +1292,7 @@ impl<'s> Session<'s> { | Value::Float(_) | Value::Uuid(_) | Value::EndSentinel + | Value::Bytes(_) | Value::Text(_) => unreachable!(), Value::List(_) | Value::Dict(_) => { Err(Err(CozoError::InvalidArgument)) diff --git a/src/relation/key_order.rs b/src/relation/key_order.rs index 23f69880..10ebe9a7 100644 --- a/src/relation/key_order.rs +++ b/src/relation/key_order.rs @@ -61,7 +61,7 @@ mod tests { BTreeMap::new().into(), 1e23.into(), false.into(), - "xxyx".into(), + Value::from("xxyx"), ] .into(); t.push_value(&vals); diff --git a/src/relation/tuple.rs b/src/relation/tuple.rs index 7943ae86..8ead4595 100644 --- a/src/relation/tuple.rs +++ b/src/relation/tuple.rs @@ -167,7 +167,7 @@ impl> Tuple { Tag::Int => start + self.parse_varint(start).1, Tag::Float => start + 8, Tag::Uuid => start + 16, - Tag::Text | Tag::Variable => { + Tag::Text | Tag::Variable | Tag::Bytes => { let (slen, offset) = self.parse_varint(start); let slen = slen as usize; start + slen + offset @@ -339,6 +339,13 @@ impl> Tuple { (start + slen + offset, s.into()) } + Tag::Bytes => { + let (slen, offset) = self.parse_varint(start); + let slen = slen as usize; + let s = &data[start + offset..start + offset + slen]; + + (start + slen + offset, s.into()) + } Tag::Variable => { let (slen, offset) = self.parse_varint(start); let slen = slen as usize; @@ -584,6 +591,14 @@ impl OwnTuple { self.idx_cache.borrow_mut().push(self.data.len()); } #[inline] + pub fn push_bytes(&mut self, b: impl AsRef<[u8]>) { + let b = b.as_ref(); + self.push_tag(Tag::Bytes); + self.push_varint(b.len() as u64); + self.data.extend_from_slice(b); + self.idx_cache.borrow_mut().push(self.data.len()); + } + #[inline] pub fn push_variable(&mut self, s: impl AsRef) { let s = s.as_ref(); self.push_tag(Tag::Variable); @@ -600,6 +615,7 @@ impl OwnTuple { Value::Float(f) => self.push_float(f.into_inner()), Value::Uuid(u) => self.push_uuid(*u), Value::Text(t) => self.push_str(t), + Value::Bytes(b) => self.push_bytes(b), Value::Variable(s) => self.push_variable(s), Value::List(l) => { self.push_tag(Tag::List); @@ -782,7 +798,7 @@ mod tests { t.push_null(); t.push_str("abcdef"); t.push_null(); - t.push_value(&vec![true.into(), 1e236.into(), "xxyyzz".into()].into()); + t.push_value(&vec![true.into(), 1e236.into(), Value::from("xxyyzz")].into()); t.push_int(-123345); t.push_value(&BTreeMap::from([]).into()); t.push_int(12121212); @@ -816,7 +832,7 @@ mod tests { Value::from(Value::from(vec![ true.into(), 1e236.into(), - "xxyyzz".into(), + Value::from("xxyyzz"), ])), t.get(6).unwrap() ); @@ -861,7 +877,7 @@ mod tests { Value::from(Value::from(vec![ true.into(), 1e236.into(), - "xxyyzz".into(), + Value::from("xxyyzz"), ])), t.get(6).unwrap() ); diff --git a/src/relation/value.rs b/src/relation/value.rs index 65dce99f..3994ec6d 100644 --- a/src/relation/value.rs +++ b/src/relation/value.rs @@ -26,6 +26,8 @@ pub enum Tag { Text = 6, Uuid = 7, + Bytes = 64, + List = 128, Dict = 129, @@ -53,6 +55,8 @@ impl TryFrom for Tag { 6 => Text, 7 => Uuid, + 64 => Bytes, + 128 => List, 129 => Dict, @@ -104,6 +108,7 @@ pub enum Value<'a> { Float(OrderedFloat), Uuid(Uuid), Text(Cow<'a, str>), + Bytes(Cow<'a, [u8]>), // maybe evaluated List(Vec>), Dict(BTreeMap, Value<'a>>), @@ -165,7 +170,8 @@ impl<'a> Value<'a> { } Value::IdxAccess(idx, value) => Value::IdxAccess(idx, value.to_static().into()), Value::TupleRef(tid, cid) => Value::TupleRef(tid, cid), - Value::DescSort(Reverse(val)) => Value::DescSort(Reverse(val.to_static().into())) + Value::DescSort(Reverse(val)) => Value::DescSort(Reverse(val.to_static().into())), + Value::Bytes(t) => { Value::from(t.into_owned()) } } } #[inline] @@ -177,6 +183,7 @@ impl<'a> Value<'a> { | Value::Float(_) | Value::Uuid(_) | Value::Text(_) + | Value::Bytes(_) | Value::EndSentinel => true, Value::List(l) => l.iter().all(|v| v.is_evaluated()), Value::Dict(d) => d.values().all(|v| v.is_evaluated()), @@ -219,6 +226,7 @@ impl<'a> Value<'a> { | Value::Float(_) | Value::Uuid(_) | Value::Text(_) + | Value::Bytes(_) | Value::Variable(_)) => v, Value::List(l) => Value::List( l.into_iter() @@ -309,6 +317,13 @@ impl<'a> From<&'a str> for Value<'a> { } } +impl<'a> From<&'a [u8]> for Value<'a> { + #[inline] + fn from(v: &'a [u8]) -> Self { + Value::Bytes(Cow::Borrowed(v)) + } +} + impl From for StaticValue { #[inline] fn from(s: String) -> Self { @@ -316,6 +331,13 @@ impl From for StaticValue { } } +impl From> for StaticValue { + #[inline] + fn from(v: Vec) -> Self { + Value::Bytes(Cow::Owned(v)) + } +} + impl From for StaticValue { #[inline] fn from(u: Uuid) -> Self { @@ -355,6 +377,9 @@ impl<'a> Display for Value<'a> { Value::Uuid(u) => { write!(f, "{}", u)?; } + Value::Bytes(b) => { + write!(f, "<{} bytes: {:?} ..>", b.len(), &b[..8])?; + } Value::Text(t) => { f.write_char('"')?; for char in t.chars() {