Skip to content

fix: make get functions public + documentation for getter apis #82

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
13 changes: 13 additions & 0 deletions README.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this documentation to be on doc comments?

Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,19 @@ fn process_schema(text: [u8; NUM_BYTES])
}
```

## Getters API

#### Function name differences

- **Checked vs Unchecked**
- `get_*`/`get_*_var` return `Option<T>`; 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<u8, KeyBytes>` for variable-length keys up to `KeyBytes`.


# Edge Cases

### single value JSON
Expand Down
34 changes: 14 additions & 20 deletions src/get_array.nr
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use crate::utils::cast_num_to_u32;
impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let MaxNumValues: u32, let MaxKeyFields: u32> JSON<NumBytes, NumPackedFields, MaxNumTokens, MaxNumValues, MaxKeyFields> {

/**
* @brief if the root JSON is an array, return its length
* @brief Returns its length when the current root is an array; errors otherwise.
**/
pub(crate) fn get_length(self) -> 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();
Expand All @@ -23,9 +23,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an object, extract an array given by `key`
* @description returns an Option<JSON> 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<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Option<Self> {
pub 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();
Expand All @@ -49,9 +49,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an object, extract an array given by `key`
* @description will revert if the array does not exist
* @description From an object root, returns the array at key; errors otherwise.
**/
pub(crate) fn get_array_unchecked<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Self {
pub 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);
Expand All @@ -67,12 +67,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
}

/**
* @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<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> Option<Self> {
pub fn get_array_var<let KeyBytes: u32>(self, key: BoundedVec<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_var(key);
let entry: JSONEntry = self.json_entries_packed[key_index].into();
Expand All @@ -99,12 +96,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
}

/**
* @brief same as `get_array_unchecked` for where the key length may be less than KeyBytes
* @brief Same as `get_array_unchecked`, but with a variable-length key.
**/
pub(crate) fn get_array_unchecked_var<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> Self {
pub fn get_array_unchecked_var<let KeyBytes: u32>(self, key: BoundedVec<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_var(key);
Expand All @@ -121,9 +115,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an array, extract an array given by the position of the target in the source array
* @description returns an Option<JSON> 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<Self> {
pub fn get_array_from_array(self, array_index: Field) -> Option<Self> {
assert(
self.layer_type_of_root == ARRAY_LAYER,
"can only acceess array elements from array",
Expand Down Expand Up @@ -158,9 +152,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an array, extract an array given by the position of the target in the source array
* @description will revert if the array does not exist
* @description When the current root is an array, returns the nested array at `index`. Errors if `index` is out of bounds or the element is not an array.
**/
pub(crate) fn get_array_from_array_unchecked(self, array_index: Field) -> 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",
Expand Down
23 changes: 12 additions & 11 deletions src/get_literal.nr
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,15 @@ 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<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let MaxNumValues: u32, let MaxKeyFields: u32> JSON<NumBytes, NumPackedFields, MaxNumTokens, MaxNumValues, MaxKeyFields> {

/**
* @brief if the root JSON is an object, extract a literal value given by `key`
* @description returns an Option<JSONLiteral> 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.
**/
pub(crate) fn get_literal<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Option<JSONLiteral> {
pub 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);
Expand All @@ -93,9 +94,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @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.
**/
fn get_literal_unchecked<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> JSONLiteral {
pub 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);
Expand All @@ -110,9 +111,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
}

/**
* @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`.
**/
fn get_literal_var<let KeyBytes: u32>(
pub fn get_literal_var<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> Option<JSONLiteral> {
Expand All @@ -134,9 +135,9 @@ 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
* @brief Same as `get_literal_unchecked`, with a variable-length key.
**/
fn get_literal_unchecked_var<let KeyBytes: u32>(
pub fn get_literal_unchecked_var<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> JSONLiteral {
Expand All @@ -155,7 +156,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an array, extract a literal given by the position of the target in the source array
* @description returns an Option<JSONLiteral> 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<JSONLiteral> {
assert(
Expand Down Expand Up @@ -191,9 +192,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an array, extract a literal given by the position of the target in the source array
* @description will revert if the literal does not exist
* @description When the current root is an array, returns the literal at `index`; errors if `index` is out of bounds or the element is not a literal.
**/
fn get_literal_from_array_unchecked(self, array_index: Field) -> 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",
Expand Down
34 changes: 14 additions & 20 deletions src/get_number.nr
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an object, extract a numeric value given by `key`
* @description returns an Option<u64> 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<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Option<u64> {
pub 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,
Expand All @@ -71,9 +71,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an object, extract a u64 value given by `key`
* @description will revert if the number does not exist
* @description From an object root, returns the number at `key`; errors if the key is missing, not a number, or if called when the current root is an array.
**/
fn get_number_unchecked<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> u64 {
pub 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,
Expand All @@ -85,9 +85,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
}

/**
* @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`.
**/
fn get_number_var<let KeyBytes: u32>(self, key: BoundedVec<u8, KeyBytes>) -> Option<u64> {
pub 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 @@ -103,9 +103,9 @@ 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
* @brief Same as `get_number_unchecked`, with a variable-length key.
**/
fn get_number_unchecked_var<let KeyBytes: u32>(self, key: BoundedVec<u8, KeyBytes>) -> u64 {
pub 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 All @@ -118,13 +118,10 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an array, extract a numeric value given by the position of the target in the source array
* @description returns an Option<u64> 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<u64> {
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<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();
Expand Down Expand Up @@ -153,13 +150,10 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an array, extract a numeric value given by the position of the target in the source array
* @description will revert if the number does not exist
* @description When the current root is an array, returns the number at `index`; errors if `index` is out of bounds or the element is not a number.
**/
fn get_number_from_array_unchecked(self, array_index: Field) -> 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();
Expand Down
29 changes: 12 additions & 17 deletions src/get_object.nr
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ use crate::utils::cast_num_to_u32;
impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let MaxNumValues: u32, let MaxKeyFields: u32> JSON<NumBytes, NumPackedFields, MaxNumTokens, MaxNumValues, MaxKeyFields> {

/**
* @brief if the root JSON is an object, extract a child object given by `key`
* @description returns an Option<JSON> where, if the object exists, the JSON object will have the requested object as its root value
* @brief From an object root, returns `Some(JSON)` if `key` exists and is an object, `None` if `key` is missing; errors if `key` exists but is not an object, or if called when the current root is an array.
**/
pub(crate) fn get_object<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Option<Self> {
pub 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);
Expand All @@ -37,10 +36,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
}

/**
* @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
* @brief From an object root, returns the object at `key`; errors otherwise.
**/
pub(crate) fn get_object_unchecked<let KeyBytes: u32>(self, key: [u8; KeyBytes]) -> Self {
pub 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();
Expand All @@ -58,12 +56,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
}

/**
* @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<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> Option<Self> {
pub fn get_object_var<let KeyBytes: u32>(self, key: BoundedVec<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_var(key);
Expand All @@ -86,9 +81,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
}

/**
* @brief same as `get_object_unchecked` for where the key length may be less than KeyBytes
* @brief Same as `get_object_unchecked`, but with a variable-length key.
**/
pub(crate) fn get_object_unchecked_var<let KeyBytes: u32>(
pub fn get_object_unchecked_var<let KeyBytes: u32>(
self,
key: BoundedVec<u8, KeyBytes>,
) -> Self {
Expand All @@ -110,9 +105,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an array, extract an object given by the position of the target in the source array
* @description returns an Option<JSON> 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<Self> {
pub fn get_object_from_array(self, array_index: Field) -> Option<Self> {
assert(
self.layer_type_of_root == ARRAY_LAYER,
"can only acceess array elements from array",
Expand Down Expand Up @@ -148,9 +143,9 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max

/**
* @brief if the root JSON is an array, extract an object given by the position of the target in the source array
* @description will revert if the object does not exist
* @description When the current root is an array, returns the object at `index`. Errors if `index` is out of bounds or the element is not an object.
**/
pub(crate) fn get_object_from_array_unchecked(self, array_index: Field) -> Self {
pub fn get_object_from_array_unchecked(self, array_index: Field) -> Self {
assert(
self.layer_type_of_root == ARRAY_LAYER,
"can only acceess array elements from array",
Expand Down
Loading