summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/unit/kv_test.ts28
-rw-r--r--ext/kv/codec.rs16
-rw-r--r--ext/kv/lib.rs18
3 files changed, 42 insertions, 20 deletions
diff --git a/cli/tests/unit/kv_test.ts b/cli/tests/unit/kv_test.ts
index 256060ccc..1c0eed002 100644
--- a/cli/tests/unit/kv_test.ts
+++ b/cli/tests/unit/kv_test.ts
@@ -600,6 +600,14 @@ dbTest("list prefix with end empty", async (db) => {
assertEquals(entries.length, 0);
});
+dbTest("list prefix with empty prefix", async (db) => {
+ await db.set(["a"], 1);
+ const entries = await collect(db.list({ prefix: [] }));
+ assertEquals(entries, [
+ { key: ["a"], value: 1, versionstamp: "00000000000000010000" },
+ ]);
+});
+
dbTest("list prefix reverse", async (db) => {
await setupData(db);
@@ -966,3 +974,23 @@ dbTest("invalid mutation type rejects", async (db) => {
.commit();
}, TypeError);
});
+
+dbTest("key ordering", async (db) => {
+ await db.atomic()
+ .set([new Uint8Array(0x1)], 0)
+ .set(["a"], 0)
+ .set([1n], 0)
+ .set([3.14], 0)
+ .set([false], 0)
+ .set([true], 0)
+ .commit();
+
+ assertEquals((await collect(db.list({ prefix: [] }))).map((x) => x.key), [
+ [new Uint8Array(0x1)],
+ ["a"],
+ [1n],
+ [3.14],
+ [false],
+ [true],
+ ]);
+});
diff --git a/ext/kv/codec.rs b/ext/kv/codec.rs
index b2acfdbc2..522c2e9bc 100644
--- a/ext/kv/codec.rs
+++ b/ext/kv/codec.rs
@@ -34,14 +34,6 @@ pub fn canonicalize_f64(n: f64) -> f64 {
}
pub fn encode_key(key: &Key) -> std::io::Result<Vec<u8>> {
- // Disallow empty key
- if key.0.is_empty() {
- return Err(std::io::Error::new(
- std::io::ErrorKind::InvalidInput,
- "key should not be empty",
- ));
- }
-
let mut output: Vec<u8> = vec![];
for part in &key.0 {
match part {
@@ -73,14 +65,6 @@ pub fn encode_key(key: &Key) -> std::io::Result<Vec<u8>> {
}
pub fn decode_key(mut bytes: &[u8]) -> std::io::Result<Key> {
- // Disallow empty key
- if bytes.is_empty() {
- return Err(std::io::Error::new(
- std::io::ErrorKind::InvalidInput,
- "key should not be empty",
- ));
- }
-
let mut key = Key(vec![]);
while !bytes.is_empty() {
let tag = bytes[0];
diff --git a/ext/kv/lib.rs b/ext/kv/lib.rs
index 49a59af74..2d4bae6fc 100644
--- a/ext/kv/lib.rs
+++ b/ext/kv/lib.rs
@@ -102,8 +102,8 @@ type KvKey = Vec<AnyValue>;
impl From<AnyValue> for KeyPart {
fn from(value: AnyValue) -> Self {
match value {
- AnyValue::Bool(false) => KeyPart::True,
- AnyValue::Bool(true) => KeyPart::False,
+ AnyValue::Bool(false) => KeyPart::False,
+ AnyValue::Bool(true) => KeyPart::True,
AnyValue::Number(n) => KeyPart::Float(n),
AnyValue::BigInt(n) => KeyPart::Int(n),
AnyValue::String(s) => KeyPart::String(s),
@@ -115,8 +115,8 @@ impl From<AnyValue> for KeyPart {
impl From<KeyPart> for AnyValue {
fn from(value: KeyPart) -> Self {
match value {
- KeyPart::True => AnyValue::Bool(false),
- KeyPart::False => AnyValue::Bool(true),
+ KeyPart::False => AnyValue::Bool(false),
+ KeyPart::True => AnyValue::Bool(true),
KeyPart::Float(n) => AnyValue::Number(n),
KeyPart::Int(n) => AnyValue::BigInt(n),
KeyPart::String(s) => AnyValue::String(s),
@@ -499,6 +499,16 @@ where
resource.db.clone()
};
+ for key in checks
+ .iter()
+ .map(|c| &c.0)
+ .chain(mutations.iter().map(|m| &m.0))
+ {
+ if key.is_empty() {
+ return Err(type_error("key cannot be empty"));
+ }
+ }
+
let checks = checks
.into_iter()
.map(TryInto::try_into)