Skip to content

Commit

Permalink
chore: replace nested matches in noirc_abi (#1670)
Browse files Browse the repository at this point in the history
* chore: replace nested matches in `noirc_abi`

* chore: restore ability to pass numbers for bools
  • Loading branch information
TomAFrench authored Jun 14, 2023
1 parent 07b07d0 commit e299b5c
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 75 deletions.
76 changes: 44 additions & 32 deletions crates/noirc_abi/src/input_parser/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,56 +98,68 @@ impl InputValue {
param_type: &AbiType,
arg_name: &str,
) -> Result<InputValue, InputParserError> {
let input_value = match value {
JsonTypes::String(string) => match param_type {
AbiType::String { .. } => InputValue::String(string),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => {
InputValue::Field(parse_str_to_field(&string)?)
}

AbiType::Array { .. } | AbiType::Struct { .. } => {
return Err(InputParserError::AbiTypeMismatch(param_type.clone()))
}
},
JsonTypes::Integer(integer) => {
let input_value = match (value, param_type) {
(JsonTypes::String(string), AbiType::String { .. }) => InputValue::String(string),
(
JsonTypes::String(string),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean,
) => InputValue::Field(parse_str_to_field(&string)?),

(
JsonTypes::Integer(integer),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean,
) => {
let new_value = FieldElement::from(i128::from(integer));

InputValue::Field(new_value)
}
JsonTypes::Bool(boolean) => InputValue::Field(boolean.into()),
JsonTypes::ArrayNum(arr_num) => {

(JsonTypes::Bool(boolean), AbiType::Boolean) => InputValue::Field(boolean.into()),

(JsonTypes::ArrayNum(arr_num), AbiType::Array { typ, .. })
if matches!(
typ.as_ref(),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean
) =>
{
let array_elements =
vecmap(arr_num, |elem_num| FieldElement::from(i128::from(elem_num)));

InputValue::Vec(array_elements)
}
JsonTypes::ArrayString(arr_str) => {
(JsonTypes::ArrayString(arr_str), AbiType::Array { typ, .. })
if matches!(
typ.as_ref(),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean
) =>
{
let array_elements = try_vecmap(arr_str, |elem_str| parse_str_to_field(&elem_str))?;

InputValue::Vec(array_elements)
}
JsonTypes::ArrayBool(arr_bool) => {
(JsonTypes::ArrayBool(arr_bool), AbiType::Array { typ, .. })
if matches!(typ.as_ref(), AbiType::Boolean) =>
{
let array_elements = vecmap(arr_bool, FieldElement::from);

InputValue::Vec(array_elements)
}

JsonTypes::Table(table) => match param_type {
AbiType::Struct { fields } => {
let native_table = try_btree_map(fields, |(field_name, abi_type)| {
// Check that json contains a value for each field of the struct.
let field_id = format!("{arg_name}.{field_name}");
let value = table
.get(field_name)
.ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?;
InputValue::try_from_json(value.clone(), abi_type, &field_id)
.map(|input_value| (field_name.to_string(), input_value))
})?;

InputValue::Struct(native_table)
}
_ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
},
(JsonTypes::Table(table), AbiType::Struct { fields }) => {
let native_table = try_btree_map(fields, |(field_name, abi_type)| {
// Check that json contains a value for each field of the struct.
let field_id = format!("{arg_name}.{field_name}");
let value = table
.get(field_name)
.ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?;
InputValue::try_from_json(value.clone(), abi_type, &field_id)
.map(|input_value| (field_name.to_string(), input_value))
})?;

InputValue::Struct(native_table)
}

(_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
};

Ok(input_value)
Expand Down
76 changes: 44 additions & 32 deletions crates/noirc_abi/src/input_parser/toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,56 +95,68 @@ impl InputValue {
param_type: &AbiType,
arg_name: &str,
) -> Result<InputValue, InputParserError> {
let input_value = match value {
TomlTypes::String(string) => match param_type {
AbiType::String { .. } => InputValue::String(string),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => {
InputValue::Field(parse_str_to_field(&string)?)
}

AbiType::Array { .. } | AbiType::Struct { .. } => {
return Err(InputParserError::AbiTypeMismatch(param_type.clone()))
}
},
TomlTypes::Integer(integer) => {
let input_value = match (value, param_type) {
(TomlTypes::String(string), AbiType::String { .. }) => InputValue::String(string),
(
TomlTypes::String(string),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean,
) => InputValue::Field(parse_str_to_field(&string)?),

(
TomlTypes::Integer(integer),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean,
) => {
let new_value = FieldElement::from(i128::from(integer));

InputValue::Field(new_value)
}
TomlTypes::Bool(boolean) => InputValue::Field(boolean.into()),
TomlTypes::ArrayNum(arr_num) => {

(TomlTypes::Bool(boolean), AbiType::Boolean) => InputValue::Field(boolean.into()),

(TomlTypes::ArrayNum(arr_num), AbiType::Array { typ, .. })
if matches!(
typ.as_ref(),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean
) =>
{
let array_elements =
vecmap(arr_num, |elem_num| FieldElement::from(i128::from(elem_num)));

InputValue::Vec(array_elements)
}
TomlTypes::ArrayString(arr_str) => {
(TomlTypes::ArrayString(arr_str), AbiType::Array { typ, .. })
if matches!(
typ.as_ref(),
AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean
) =>
{
let array_elements = try_vecmap(arr_str, |elem_str| parse_str_to_field(&elem_str))?;

InputValue::Vec(array_elements)
}
TomlTypes::ArrayBool(arr_bool) => {
(TomlTypes::ArrayBool(arr_bool), AbiType::Array { typ, .. })
if matches!(typ.as_ref(), AbiType::Boolean) =>
{
let array_elements = vecmap(arr_bool, FieldElement::from);

InputValue::Vec(array_elements)
}

TomlTypes::Table(table) => match param_type {
AbiType::Struct { fields } => {
let native_table = try_btree_map(fields, |(field_name, abi_type)| {
// Check that toml contains a value for each field of the struct.
let field_id = format!("{arg_name}.{field_name}");
let value = table
.get(field_name)
.ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?;
InputValue::try_from_toml(value.clone(), abi_type, &field_id)
.map(|input_value| (field_name.to_string(), input_value))
})?;

InputValue::Struct(native_table)
}
_ => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
},
(TomlTypes::Table(table), AbiType::Struct { fields }) => {
let native_table = try_btree_map(fields, |(field_name, abi_type)| {
// Check that json contains a value for each field of the struct.
let field_id = format!("{arg_name}.{field_name}");
let value = table
.get(field_name)
.ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?;
InputValue::try_from_toml(value.clone(), abi_type, &field_id)
.map(|input_value| (field_name.to_string(), input_value))
})?;

InputValue::Struct(native_table)
}

(_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())),
};

Ok(input_value)
Expand Down
23 changes: 12 additions & 11 deletions crates/noirc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,22 +302,23 @@ impl Abi {

fn encode_value(value: InputValue, abi_type: &AbiType) -> Result<Vec<FieldElement>, AbiError> {
let mut encoded_value = Vec::new();
match value {
InputValue::Field(elem) => encoded_value.push(elem),
InputValue::Vec(vec_elem) => encoded_value.extend(vec_elem),
InputValue::String(string) => {
match (value, abi_type) {
(InputValue::Field(elem), _) => encoded_value.push(elem),

(InputValue::Vec(vec_elem), _) => encoded_value.extend(vec_elem),

(InputValue::String(string), _) => {
let str_as_fields =
string.bytes().map(|byte| FieldElement::from_be_bytes_reduce(&[byte]));
encoded_value.extend(str_as_fields);
}
InputValue::Struct(object) => match abi_type {
AbiType::Struct { fields } => {
for (field, typ) in fields {
encoded_value.extend(Self::encode_value(object[field].clone(), typ)?);
}

(InputValue::Struct(object), AbiType::Struct { fields }) => {
for (field, typ) in fields {
encoded_value.extend(Self::encode_value(object[field].clone(), typ)?);
}
_ => unreachable!("value should have already been checked to match abi type"),
},
}
_ => unreachable!("value should have already been checked to match abi type"),
}
Ok(encoded_value)
}
Expand Down

0 comments on commit e299b5c

Please sign in to comment.