Skip to content

chore: strip out duplicate implementations of fixed and variable length keys #84

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 2 additions & 21 deletions src/get_array.nr
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,15 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
* @description returns an Option<JSON> where, if the array exists, the JSON object will have the requested array as its root value
**/
pub(crate) fn get_array<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Option<Self> {
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");
let (exists, key_index) = self.key_exists_impl(key);
let entry: JSONEntry = self.json_entries_packed[key_index].into();
assert(
(entry.entry_type - END_ARRAY_TOKEN as Field) * exists as Field == 0,
"key does not describe an object",
);

let result = self.update_json_array(entry, key_index);

if exists {
Option::some(result)
} else {
Option::none()
}
self.get_array_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
* @brief if the root JSON is an object, extract an array given by `key`
* @description will revert if the array does not exist
**/
pub(crate) fn get_array_unchecked<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Self {
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");

let (entry, key_index) = self.get_json_entry_unchecked_with_key_index(key);
assert(entry.entry_type == END_ARRAY_TOKEN as Field, "key does not describe an object");

self.update_json_array(entry, key_index)
self.get_array_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand Down
32 changes: 4 additions & 28 deletions src/get_literal.nr
Original file line number Diff line number Diff line change
Expand Up @@ -74,45 +74,21 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
* @description returns an Option<JSONLiteral> which will be null if the literal does not exist
**/
pub(crate) fn get_literal<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Option<JSONLiteral> {
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");

let (exists, entry) = self.get_json_entry(key);
assert(
(entry.entry_type - LITERAL_TOKEN as Field) * exists as Field == 0,
"get_literal: entry exists but is not a literal!",
);
let mut parsed_string: [u8; MAX_LITERAL_LENGTH_AS_STRING] =
self.extract_string_entry(entry);

if exists {
Option::some(extract_literal_from_array(parsed_string, entry.json_length))
} else {
Option::none()
}
self.get_literal_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
* @brief if the root JSON is an object, extract a literal value given by `key`
* @description will revert if the literal does not exist
**/
fn get_literal_unchecked<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> JSONLiteral {
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");

let entry = self.get_json_entry_unchecked(key);
assert(
entry.entry_type == LITERAL_TOKEN as Field,
"get_literal_unchecked_var: entry exists but is not a literal!",
);
let mut parsed_string: [u8; MAX_LITERAL_LENGTH_AS_STRING] =
self.extract_string_entry(entry);

extract_literal_from_array(parsed_string, entry.json_length)
self.get_literal_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
* @brief same as `get_literal` for where the key length may be less than KeyBytes
**/
fn get_literal_var<let KeyBytes: u32>(
pub(crate) fn get_literal_var<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> Option<JSONLiteral> {
Expand All @@ -136,7 +112,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
/**
* @brief same as `get_literal_unchecked` for where the key length may be less than KeyBytes
**/
fn get_literal_unchecked_var<let KeyBytes: u32>(
pub(crate) fn get_literal_unchecked_var<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> JSONLiteral {
Expand Down
32 changes: 10 additions & 22 deletions src/get_number.nr
Original file line number Diff line number Diff line change
Expand Up @@ -55,39 +55,24 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
* @description returns an Option<u64> which will be null if the key does not exist
**/
pub(crate) fn get_number<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Option<u64> {
let (exists, entry) = self.get_json_entry(key);
assert(
(entry.entry_type - NUMERIC_TOKEN as Field) * exists as Field == 0,
"get_number: entry exists but is not a number!",
);
let mut parsed_string: [u8; U64_LENGTH_AS_BASE10_STRING] = self.extract_string_entry(entry);

if exists {
Option::some(extract_number_from_array(parsed_string, entry.json_length))
} else {
Option::none()
}
self.get_number_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
* @brief if the root JSON is an object, extract a u64 value given by `key`
* @description will revert if the number does not exist
**/
fn get_number_unchecked<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> u64 {
let entry = self.get_json_entry_unchecked(key);
assert(
entry.entry_type == NUMERIC_TOKEN as Field,
"get_number_unchecked: entry exists but is not a number!",
);
let mut parsed_string: [u8; U64_LENGTH_AS_BASE10_STRING] = self.extract_string_entry(entry);

extract_number_from_array(parsed_string, entry.json_length)
self.get_number_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
* @brief same as `get_number` for where the key length may be less than KeyBytes
**/
fn get_number_var<let KeyBytes: u32>(self, key: BoundedVec<u8, KeyBytes>) -> Option<u64> {
pub(crate) fn get_number_var<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> Option<u64> {
let (exists, entry) = self.get_json_entry_var(key);
assert(
(entry.entry_type - NUMERIC_TOKEN as Field) * exists as Field == 0,
Expand All @@ -105,7 +90,10 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
/**
* @brief same as `get_number_unchecked` for where the key length may be less than KeyBytes
**/
fn get_number_unchecked_var<let KeyBytes: u32>(self, key: BoundedVec<u8, KeyBytes>) -> u64 {
pub(crate) fn get_number_unchecked_var<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> u64 {
let entry = self.get_json_entry_unchecked_var(key);
assert(
entry.entry_type == NUMERIC_TOKEN as Field,
Expand Down
27 changes: 2 additions & 25 deletions src/get_object.nr
Original file line number Diff line number Diff line change
Expand Up @@ -25,38 +25,15 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
* @description returns an Option<JSON> where, if the object exists, the JSON object will have the requested object as its root value
**/
pub(crate) fn get_object<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Option<Self> {
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");

let (exists, key_index) = self.key_exists_impl(key);
let entry: JSONEntry = self.json_entries_packed[key_index].into();
assert(
(entry.entry_type - END_OBJECT_TOKEN as Field) * exists as Field == 0,
"get_object: entry exists but is not an object!",
);

let result = self.update_json_object(entry, key_index);

if exists {
Option::some(result)
} else {
Option::none()
}
self.get_object_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
* @brief if the root JSON is an object, extract a child object given by `key`
* @description will revert if the requested object does not exist
**/
pub(crate) fn get_object_unchecked<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Self {
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");
let (entry, key_index) = self.get_json_entry_unchecked_with_key_index(key);
let entry: JSONEntry = self.json_entries_packed[key_index].into();
assert(
entry.entry_type == END_OBJECT_TOKEN as Field,
"get_object: entry exists but is not an object!",
);

self.update_json_object(entry, key_index)
self.get_object_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand Down
51 changes: 4 additions & 47 deletions src/get_string.nr
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
self,
key: [u8; KeyBytes],
) -> Option<BoundedVec<u8, StringBytes>> {
let (exists, entry) = self.get_json_entry(key);
assert(
(entry.entry_type - STRING_TOKEN as Field) * exists as Field == 0,
"get_string: entry exists but is not a string!",
);
let mut parsed_string: [u8; StringBytes] = self.extract_string_entry(entry);

let parsed_string: BoundedVec<u8, StringBytes> = process_escape_sequences(
BoundedVec::from_parts_unchecked(parsed_string, entry.json_length as u32),
);

if exists {
Option::some(parsed_string)
} else {
Option::none()
}
self.get_string_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand All @@ -132,16 +117,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
self,
key: [u8; KeyBytes],
) -> BoundedVec<u8, StringBytes> {
let entry = self.get_json_entry_unchecked(key);
assert(
entry.entry_type == STRING_TOKEN as Field,
"get_string_unchecked: entry exists but is not a string!",
);
let parsed_string = BoundedVec::from_parts_unchecked(
self.extract_string_entry(entry),
entry.json_length as u32,
);
process_escape_sequences(parsed_string)
self.get_string_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand Down Expand Up @@ -294,19 +270,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
self,
key: [u8; KeyBytes],
) -> Option<JSONValue<StringBytes>> {
let (exists, entry) = self.get_json_entry(key);
let mut parsed_string: [u8; StringBytes] = self.extract_string_entry(entry);

let parsed_string: BoundedVec<u8, StringBytes> =
BoundedVec::from_parts_unchecked(parsed_string, entry.json_length as u32);

if exists {
Option::some(
JSONValue { value: parsed_string, value_type: entry.entry_type },
)
} else {
Option::none()
}
self.get_value_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand All @@ -318,14 +282,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
self,
key: [u8; KeyBytes],
) -> JSONValue<StringBytes> {
let entry = self.get_json_entry_unchecked(key);
JSONValue {
value: BoundedVec::from_parts_unchecked(
self.extract_string_entry(entry),
entry.json_length as u32,
),
value_type: entry.entry_type,
}
self.get_value_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand Down
95 changes: 7 additions & 88 deletions src/getters.nr
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
self,
key: [u8; KeyBytes],
) -> (bool, JSONEntry) {
// let key_index = self.find_key_in_map(keyhash);
// assert(self.key_hashes[key_index] == keyhash);
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");

let (exists, key_index) = self.key_exists_impl(key);
let entry: JSONEntry = self.json_entries_packed[key_index].into();
(exists, entry)
self.get_json_entry_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand All @@ -48,21 +42,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
self,
key: [u8; KeyBytes],
) -> JSONEntry {
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");

let hasher: ByteHasher<MaxKeyFields> = ByteHasher {};
let keyhash = hasher.get_keyhash_var(key, 0, KeyBytes);
let two_pow_216 = 0x100000000000000000000000000000000000000000000000000000000;

let keyhash = keyhash + self.root_id * two_pow_216;

// Safety: The assertion below checks that the keyhash is stored in the the index returned by the unconstrained function
let key_index = unsafe { find_key_in_map::<MaxNumValues>(self.key_hashes, keyhash) };

assert_eq(self.key_hashes[key_index], keyhash, "get_json_entry_unchecked: key not found");
let entry: JSONEntry = self.json_entries_packed[key_index].into();

entry
self.get_json_entry_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand Down Expand Up @@ -112,21 +92,10 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
self,
key: [u8; KeyBytes],
) -> (JSONEntry, u32) {
assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key");

let hasher: ByteHasher<MaxKeyFields> = ByteHasher {};
let keyhash = hasher.get_keyhash_var(key, 0, KeyBytes);
let two_pow_216 = 0x100000000000000000000000000000000000000000000000000000000;

let keyhash = keyhash + self.root_id * two_pow_216;

// Safety: The assertion below checks that the keyhash is stored in the the index returned by the unconstrained function
let key_index = unsafe { find_key_in_map::<MaxNumValues>(self.key_hashes, keyhash) };

assert_eq(self.key_hashes[key_index], keyhash, "get_json_entry_unchecked: key not found");
let entry: JSONEntry = self.json_entries_packed[key_index].into();

(entry, key_index)
self.get_json_entry_unchecked_with_key_index_var(BoundedVec::from_parts_unchecked(
key,
KeyBytes,
))
}
/**
* @brief same as `get_json_entry_unchecked_var` but also returns the position of the JSONEntry in `self.json_entries_packed`
Expand Down Expand Up @@ -187,57 +156,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
* If it does *not* exist, we can find two adjacent entries in `key_hashes` where `key_hashes[i]` < target_key_hash < `key_hashes[i+1]`
**/
pub(crate) fn key_exists_impl<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> (bool, u32) {
/*
Option A: key exists
Option B: key does NOT exist
If key does NOT exist. 3 cases
case 1: keyhash < first entry
case 2: keyhash > last entry
case 3: entry A > keyhash > entryB
*/
let hasher: ByteHasher<MaxKeyFields> = ByteHasher {};
let keyhash = hasher.get_keyhash_var(key, 0, KeyBytes);

let HASH_MAXIMUM = 0x1000000000000000000000000000000000000000000000000000000000000 - 1;
let two_pow_216 = 0x100000000000000000000000000000000000000000000000000000000;

let keyhash = keyhash + self.root_id * two_pow_216;

// Safety: The assertion below checks that the keyhash is stored in the the index returned by the unconstrained function
let search_result =
unsafe { search_for_key_in_map::<MaxNumValues>(self.key_hashes, keyhash) };
if search_result.found {
assert_eq(search_result.lhs_index, search_result.rhs_index);
}

let found = search_result.found as Field;

let target_lt_smallest_entry = search_result.target_lt_smallest_entry as Field;
let target_gt_largest_entry = search_result.target_gt_largest_entry as Field;

// only one of "found", "target_lt_smallest_entry", "target_gt_largest_entry" can be true
let exclusion_test = found + target_gt_largest_entry + target_lt_smallest_entry;
assert(exclusion_test * exclusion_test == exclusion_test);

let mut lhs = self.key_hashes[search_result.lhs_index];
let mut rhs = self.key_hashes[search_result.rhs_index];

// case where hash < self.key_hashes[0]
// 0 < hash < hashes[0]
lhs = lhs * (1 - target_lt_smallest_entry);

// case where hash > self.key_hashes[last]
// largest < x < -1
rhs = rhs * (1 - target_gt_largest_entry) + target_gt_largest_entry * HASH_MAXIMUM;

// case where hash == self.key_hashes[found_index]
lhs = lhs - found;
rhs = rhs + found;

assert_gt_240_bit(keyhash, lhs);
assert_lt_240_bit(keyhash, rhs);

(search_result.found, search_result.lhs_index)
self.key_exists_impl_var(BoundedVec::from_parts_unchecked(key, KeyBytes))
}

/**
Expand Down