diff --git a/README.md b/README.md index d9ff043..e5ebb63 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,19 @@ fn process_schema(text: [u8; NUM_BYTES]) } ``` +## Getters API + +#### Function name differences + +- **Checked vs Unchecked** + - `get_*`/`get_*_var` return `Option`; use when a key or index may be absent. + - `get_*_unchecked`/`get_*_unchecked_var` return `T` and will error on missing/mismatched types. + +- **Fixed key vs Variable key** + - Functions taking `key: [u8; KeyBytes]` expect a fixed-length key known at compile time. + - Functions with `_var` take `key: BoundedVec` for variable-length keys up to `KeyBytes`. + + # Edge Cases ### single value JSON diff --git a/src/get_array.nr b/src/get_array.nr index 8292287..c6981ba 100644 --- a/src/get_array.nr +++ b/src/get_array.nr @@ -24,7 +24,7 @@ impl u32 { + pub fn get_length(self) -> u32 { assert(self.layer_type_of_root == ARRAY_LAYER, "can only get length of an array type"); let parent_entry: JSONEntry = self.json_entries_packed[self.root_index_in_transcript].into(); @@ -33,7 +33,7 @@ impl where, if the array exists, the JSON object will have the requested array as its root value + * @description From an object root, returns Some(JSON) if key exists and is an array, None if key is missing; errors if key exists but is not an array, or if called when the current root is an array. **/ pub(crate) fn get_array(self, key: [u8; KeyBytes]) -> Option { self.get_array_var(BoundedVec::from_parts_unchecked(key, KeyBytes)) @@ -41,19 +41,16 @@ impl(self, key: [u8; KeyBytes]) -> Self { self.get_array_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes)) } /** - * @brief same as `get_array` for where the key length may be less than KeyBytes + * @brief Same as `get_array`, but the key can be variable-length up to `KeyBytes`. **/ - pub(crate) fn get_array_var( - self, - key: BoundedVec, - ) -> Option { + pub fn get_array_var(self, key: BoundedVec) -> Option { assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key"); let (exists, key_index) = self.key_exists_impl_var(key); let entry: JSONEntry = self.json_entries_packed[key_index].into(); @@ -76,12 +73,9 @@ impl( - self, - key: BoundedVec, - ) -> Self { + pub fn get_array_unchecked_var(self, key: BoundedVec) -> 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_var(key); @@ -92,9 +86,9 @@ impl where, if the array exists, the JSON object will have the requested array as its root value + * @description When the current root is an array, returns the nested array at `index` wrapped in `Option`. Returns `None` if `index` is out of bounds; errors if in-bounds but the element is not an array. **/ - pub(crate) fn get_array_from_array(self, array_index: Field) -> Option { + pub fn get_array_from_array(self, array_index: Field) -> Option { assert( self.layer_type_of_root == ARRAY_LAYER, "can only acceess array elements from array", @@ -125,9 +119,9 @@ impl Self { + pub fn get_array_from_array_unchecked(self, array_index: Field) -> Self { assert( self.layer_type_of_root == ARRAY_LAYER, "can only acceess array elements from array", diff --git a/src/get_literal.nr b/src/get_literal.nr index 9514d4e..fce4779 100644 --- a/src/get_literal.nr +++ b/src/get_literal.nr @@ -66,29 +66,68 @@ fn extract_literal_from_array( /** * @brief getter methods for extracting literal values out of a JSON struct + * @description iterals are the JSON keywords `true`, `false`, and `null`. They are represented by `JSONLiteral`, which supports: `is_true()`, `is_false()`, `is_null()`, `to_bool()` (maps `true` to `true`, `false`/`null` to `false`) **/ impl JSON { /** * @brief if the root JSON is an object, extract a literal value given by `key` - * @description returns an Option which will be null if the literal does not exist + * @description From an object root, returns `Some(JSONLiteral)` if `key` exists and is a literal; `None` if `key` is missing; errors if `key` exists but is not a literal, or if called when the current root is an array. **/ +<<<<<<< HEAD + pub fn get_literal(self, key: [u8; KeyBytes]) -> Option { + 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() + } +======= pub(crate) fn get_literal(self, key: [u8; KeyBytes]) -> Option { self.get_literal_var(BoundedVec::from_parts_unchecked(key, KeyBytes)) +>>>>>>> 33bf55427694301d3630c946f35ac049c5563092 } /** * @brief if the root JSON is an object, extract a literal value given by `key` - * @description will revert if the literal does not exist + * @description From an object root, returns the literal at `key`; errors if the key is missing, not a literal, or if called when the current root is an array. **/ +<<<<<<< HEAD + pub fn get_literal_unchecked(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) +======= fn get_literal_unchecked(self, key: [u8; KeyBytes]) -> JSONLiteral { self.get_literal_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes)) +>>>>>>> 33bf55427694301d3630c946f35ac049c5563092 } /** - * @brief same as `get_literal` for where the key length may be less than KeyBytes + * @brief Same as `get_literal`, but accepts a variable-length key up to `KeyBytes`. **/ +<<<<<<< HEAD + pub fn get_literal_var( +======= pub(crate) fn get_literal_var( +>>>>>>> 33bf55427694301d3630c946f35ac049c5563092 self, key: BoundedVec, ) -> Option { @@ -110,9 +149,13 @@ impl( +======= pub(crate) fn get_literal_unchecked_var( +>>>>>>> 33bf55427694301d3630c946f35ac049c5563092 self, key: BoundedVec, ) -> JSONLiteral { @@ -131,7 +174,7 @@ impl which will be null if the literal does not exist + * @description When the current root is an array, returns the literal at `index` wrapped in `Option`. Returns `None` if `index` is out of bounds; errors if in-bounds but the element at `index` is not a literal. **/ fn get_literal_from_array(self, array_index: Field) -> Option { assert( @@ -167,9 +210,9 @@ impl JSONLiteral { + pub fn get_literal_from_array_unchecked(self, array_index: Field) -> JSONLiteral { assert( self.layer_type_of_root == ARRAY_LAYER, "can only acceess array elements from array", diff --git a/src/get_number.nr b/src/get_number.nr index f117b96..5e7a4c8 100644 --- a/src/get_number.nr +++ b/src/get_number.nr @@ -52,7 +52,7 @@ impl which will be null if the key does not exist + * @description From an object root, returns `Some(u64)` if `key` exists and is a number; `None` if `key` is missing; errors if `key` exists but is not a number, or if called when the current root is an array. **/ pub(crate) fn get_number(self, key: [u8; KeyBytes]) -> Option { self.get_number_var(BoundedVec::from_parts_unchecked(key, KeyBytes)) @@ -60,14 +60,14 @@ impl(self, key: [u8; KeyBytes]) -> u64 { 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 + * @brief Same as `get_number`, but accepts a variable-length key up to `KeyBytes`. **/ pub(crate) fn get_number_var( self, @@ -88,7 +88,7 @@ impl( self, @@ -106,13 +106,10 @@ impl which will be null if the number does not exist + * @description When the current root is an array, returns the number at `index` wrapped in `Option`. Returns `None` if `index` is out of bounds; errors if in-bounds but the element at `index` is not a number. **/ - fn get_number_from_array(self, array_index: Field) -> Option { - assert( - self.layer_type_of_root == ARRAY_LAYER, - "can only acceess array elements from array", - ); + pub fn get_number_from_array(self, array_index: Field) -> Option { + assert(self.layer_type_of_root == ARRAY_LAYER, "can only access array elements from array"); let parent_entry: JSONEntry = self.json_entries_packed[self.root_index_in_transcript].into(); @@ -141,13 +138,10 @@ impl u64 { - assert( - self.layer_type_of_root == ARRAY_LAYER, - "can only acceess array elements from array", - ); + pub fn get_number_from_array_unchecked(self, array_index: Field) -> u64 { + assert(self.layer_type_of_root == ARRAY_LAYER, "can only access array elements from array"); let parent_entry: JSONEntry = self.json_entries_packed[self.root_index_in_transcript].into(); diff --git a/src/get_object.nr b/src/get_object.nr index d921bc9..eb23b6c 100644 --- a/src/get_object.nr +++ b/src/get_object.nr @@ -29,20 +29,16 @@ impl(self, key: [u8; KeyBytes]) -> Self { self.get_object_unchecked_var(BoundedVec::from_parts_unchecked(key, KeyBytes)) } /** - * @brief same as `get_object` for where the key length may be less than KeyBytes + * @brief Same as `get_object`, but the key can be variable-length up to `KeyBytes`. **/ - pub(crate) fn get_object_var( - self, - key: BoundedVec, - ) -> Option { + pub fn get_object_var(self, key: BoundedVec) -> Option { assert(self.layer_type_of_root != ARRAY_LAYER, "cannot extract array elements via a key"); let (exists, key_index) = self.key_exists_impl_var(key); @@ -65,9 +61,9 @@ impl( + pub fn get_object_unchecked_var( self, key: BoundedVec, ) -> Self { @@ -85,7 +81,7 @@ impl where, if the object exists, the JSON object will have the requested object as its root value + * @description When the current root is an array, returns the object at `index` wrapped in `Option`. Returns `None` if `index` is out of bounds; errors if in-bounds but the element is not an object. **/ pub(crate) fn get_object_from_array(self, array_index: Field) -> Option { assert_eq( @@ -120,7 +116,7 @@ impl Self { assert_eq( diff --git a/src/get_string.nr b/src/get_string.nr index 1747817..dbd2850 100644 --- a/src/get_string.nr +++ b/src/get_string.nr @@ -98,10 +98,10 @@ impl which will be null if the key does not exist + * @description From an object root, returns `Some(string)` if `key` exists and is a string; `None` if `key` is missing; errors if `key` exists but is not a string, or if called when the current root is an array. * @note the `StringBytes` parameter defines the maximum allowable length of the returned string **/ - pub(crate) fn get_string( + pub fn get_string( self, key: [u8; KeyBytes], ) -> Option> { @@ -110,10 +110,10 @@ impl( + pub fn get_string_unchecked( self, key: [u8; KeyBytes], ) -> BoundedVec { @@ -121,9 +121,9 @@ impl( + pub fn get_string_var( self, key: BoundedVec, ) -> Option> { @@ -148,9 +148,9 @@ impl( + pub fn get_string_unchecked_var( self, key: BoundedVec, ) -> BoundedVec { @@ -169,9 +169,9 @@ impl which will be null if the string does not exist + * @description When the current root is an array, returns the string at `index` wrapped in `Option`. Returns `None` if `index` is out of bounds; errors if in-bounds but the element at `index` is not a string. **/ - pub(crate) fn get_string_from_array( + pub fn get_string_from_array( self, array_index: Field, ) -> Option> { @@ -210,9 +210,9 @@ impl( + pub fn get_string_from_array_unchecked( self, array_index: Field, ) -> BoundedVec { @@ -245,9 +245,9 @@ impl( + pub fn get_string_from_path( self, keys: [BoundedVec; PathDepth], ) -> Option> { @@ -273,7 +273,7 @@ impl which will be null if the key does not exist * @note the `StringBytes` parameter defines the maximum allowable length of the returned value **/ - pub(crate) fn get_value( + pub fn get_value( self, key: [u8; KeyBytes], ) -> Option> { @@ -285,7 +285,7 @@ impl( + pub fn get_value_unchecked( self, key: [u8; KeyBytes], ) -> JSONValue { @@ -317,7 +317,7 @@ impl( + pub fn get_value_unchecked_var( self, key: BoundedVec, ) -> JSONValue { @@ -335,7 +335,7 @@ impl which will be null if the value does not exist **/ - pub(crate) fn get_value_from_array( + pub fn get_value_from_array( self, array_index: Field, ) -> Option> { @@ -381,7 +381,7 @@ impl( + pub fn get_value_from_array_unchecked( self, array_index: Field, ) -> JSONValue { @@ -416,7 +416,7 @@ impl( + pub fn get_value_from_path( self, keys: [BoundedVec; PathDepth], ) -> Option> { diff --git a/src/json.nr b/src/json.nr index a39b7b7..75cac00 100644 --- a/src/json.nr +++ b/src/json.nr @@ -598,7 +598,7 @@ impl(stringbytes: [u8; StringBytes]) -> Self { + pub fn parse_json(stringbytes: [u8; StringBytes]) -> Self { assert(StringBytes <= NumBytes, "json length exceeds NumBytes!"); let mut text: [u8; NumBytes] = [0; NumBytes]; for i in 0..StringBytes {