diff --git a/server/src/coredb/htable.rs b/server/src/coredb/htable.rs index 8d9d55ec..a24bc8d5 100644 --- a/server/src/coredb/htable.rs +++ b/server/src/coredb/htable.rs @@ -310,6 +310,7 @@ where } } + use serde::ser::{SerializeSeq, Serializer}; impl Serialize for Data { diff --git a/server/src/kvengine/mod.rs b/server/src/kvengine/mod.rs index f63a4f4c..29d529a6 100644 --- a/server/src/kvengine/mod.rs +++ b/server/src/kvengine/mod.rs @@ -87,11 +87,6 @@ pub enum DdlError { TableNotEmpty, } -/// Errors arising from trying to manipulate data -pub enum ManipError { - EncodingError, -} - impl Default for KVEngine { fn default() -> Self { // by default, we don't care about the encoding scheme unless explicitly @@ -146,13 +141,86 @@ impl KVEngine { self.table.clear() } /// Get the value for a given key if it exists - pub fn get(&self, key: impl AsRef<[u8]>) -> Option> { - self.table.get(key.as_ref()) + pub fn get(&self, key: Data) -> Result>, ()> { + Ok(self.table.get(&self._encode_key(key)?)) + } + /// Check the unicode encoding of a given byte array + fn _encode(data: Data) -> Result { + if encoding::is_utf8(&data) { + Ok(data) + } else { + Err(()) + } + } + /// Check the unicode encoding of the given key, if the encoded_k flag is set + fn _encode_key(&self, key: Data) -> Result { + if self.encoded_k.load(ORD_RELAXED) { + Self::_encode(key) + } else { + Ok(key) + } + } + /// Check the unicode encoding of the given value, if the encoded_v flag is set + fn _encode_value(&self, value: Data) -> Result { + if self.encoded_v.load(ORD_RELAXED) { + Self::_encode(value) + } else { + Ok(value) + } + } + /// Set the value of a non-existent key + pub fn set(&self, key: Data, value: Data) -> Result { + Ok(self + .table + .true_if_insert(self._encode_key(key)?, self._encode_value(value)?)) + } + /// Update the value of an existing key + pub fn update(&self, key: Data, value: Data) -> Result { + Ok(self + .table + .true_if_update(self._encode_key(key)?, self._encode_value(value)?)) + } + /// Update or insert the value of a key + pub fn upsert(&self, key: Data, value: Data) -> Result<(), ()> { + self.table + .upsert(self._encode_key(key)?, self._encode_value(value)?); + Ok(()) + } + /// Remove an existing key + pub fn remove(&self, key: Data) -> Result { + Ok(self.table.true_if_removed(&self._encode_key(key)?)) } } #[test] -fn tbl() { +fn test_ignore_encoding() { + let non_unicode_value = b"Hello \xF0\x90\x80World".to_vec(); + let non_unicode_key = non_unicode_value.to_owned(); let tbl = KVEngine::default(); - assert!(tbl.get("123").is_none()); + assert!(tbl + .set(non_unicode_key.into(), non_unicode_value.into()) + .is_ok()); +} + +#[test] +fn test_bad_unicode_key() { + let bad_unicode = b"Hello \xF0\x90\x80World".to_vec(); + let tbl = KVEngine::init(true, false); + assert!(tbl.set(Data::from(bad_unicode), Data::from("123")).is_err()); +} + +#[test] +fn test_bad_unicode_value() { + let bad_unicode = b"Hello \xF0\x90\x80World".to_vec(); + let tbl = KVEngine::init(false, true); + assert!(tbl.set(Data::from("123"), Data::from(bad_unicode)).is_err()); +} + +#[test] +fn test_bad_unicode_key_value() { + let bad_unicode = b"Hello \xF0\x90\x80World".to_vec(); + let tbl = KVEngine::init(true, true); + assert!(tbl + .set(Data::from(bad_unicode.clone()), Data::from(bad_unicode)) + .is_err()); }