migrate from anyhow to thiserror (#197)
* migrate from anyhow to thiserror (#190). pending polish error msgs * Add backtrace and compartmentalize errors - Include backtraces in the errors we generate. To get this we can't just return a literal enum, because the backtrace requires a call. - Related to the previous point: add methods to create errors so we can include the backtrace conveniently without changing too much the syntax. So instead of `Err(Error::KeyNotFound(key))` (literal enum) it will be `Err(Error::key_not_found(key))` (method call) - Each error should be local to its scope, and each scope should only return its own error. - The merkle tree should return `TreeError` and not Error - The middleware should return `MiddlewareError` and not Error - With a global Error we can't easily include backend/frontend types in the error fields, so declare a `BackendError` and a `FrontendError` and follow the pattern from the previous point - The Pod traits should be able to return backend errors and will be used in the frontend; for that we change them to use trait object Error: `dyn std::error::Error` * fix error * apply suggestions from @arnaucube * rename XError and XResult to Error and Result * reorg signature * make frontend custom error more ergonomic * remove unnecessary feature --------- Co-authored-by: Eduard S. <eduardsanou@posteo.net>
This commit is contained in:
parent
58d3c6a236
commit
29545f03fc
31 changed files with 696 additions and 273 deletions
|
|
@ -45,7 +45,6 @@ use std::{
|
|||
fmt,
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use hex::{FromHex, FromHexError};
|
||||
use plonky2::{
|
||||
field::{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
//! This file implements the types defined at
|
||||
//! https://0xparc.github.io/pod2/values.html#dictionary-array-set .
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
/// This file implements the types defined at
|
||||
/// https://0xparc.github.io/pod2/values.html#dictionary-array-set .
|
||||
use anyhow::{anyhow, Result};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ use super::serialization::{ordered_map, ordered_set};
|
|||
use crate::backends::plonky2::primitives::merkletree::{MerkleProof, MerkleTree};
|
||||
use crate::{
|
||||
constants::MAX_DEPTH,
|
||||
middleware::{hash_value, Hash, Key, RawValue, Value, EMPTY_VALUE},
|
||||
middleware::{hash_value, Error, Hash, Key, RawValue, Result, Value, EMPTY_VALUE},
|
||||
};
|
||||
|
||||
/// Dictionary: the user original keys and values are hashed to be used in the leaf.
|
||||
|
|
@ -43,7 +43,7 @@ impl Dictionary {
|
|||
pub fn get(&self, key: &Key) -> Result<&Value> {
|
||||
self.kvs
|
||||
.get(key)
|
||||
.ok_or_else(|| anyhow!("key \"{}\" not found", key.name()))
|
||||
.ok_or_else(|| Error::custom(format!("key \"{}\" not found", key.name())))
|
||||
}
|
||||
pub fn prove(&self, key: &Key) -> Result<(&Value, MerkleProof)> {
|
||||
let (_, mtp) = self.mt.prove(&RawValue(key.hash().0))?;
|
||||
|
|
@ -51,15 +51,23 @@ impl Dictionary {
|
|||
Ok((value, mtp))
|
||||
}
|
||||
pub fn prove_nonexistence(&self, key: &Key) -> Result<MerkleProof> {
|
||||
self.mt.prove_nonexistence(&RawValue(key.hash().0))
|
||||
Ok(self.mt.prove_nonexistence(&RawValue(key.hash().0))?)
|
||||
}
|
||||
pub fn verify(root: Hash, proof: &MerkleProof, key: &Key, value: &Value) -> Result<()> {
|
||||
let key = RawValue(key.hash().0);
|
||||
MerkleTree::verify(MAX_DEPTH, root, proof, &key, &value.raw())
|
||||
Ok(MerkleTree::verify(
|
||||
MAX_DEPTH,
|
||||
root,
|
||||
proof,
|
||||
&key,
|
||||
&value.raw(),
|
||||
)?)
|
||||
}
|
||||
pub fn verify_nonexistence(root: Hash, proof: &MerkleProof, key: &Key) -> Result<()> {
|
||||
let key = RawValue(key.hash().0);
|
||||
MerkleTree::verify_nonexistence(MAX_DEPTH, root, proof, &key)
|
||||
Ok(MerkleTree::verify_nonexistence(
|
||||
MAX_DEPTH, root, proof, &key,
|
||||
)?)
|
||||
}
|
||||
// TODO: Rename to dict to be consistent maybe?
|
||||
pub fn kvs(&self) -> &HashMap<Key, Value> {
|
||||
|
|
@ -142,15 +150,26 @@ impl Set {
|
|||
}
|
||||
pub fn prove_nonexistence(&self, value: &Value) -> Result<MerkleProof> {
|
||||
let h = hash_value(&value.raw());
|
||||
self.mt.prove_nonexistence(&RawValue::from(h))
|
||||
Ok(self.mt.prove_nonexistence(&RawValue::from(h))?)
|
||||
}
|
||||
pub fn verify(root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> {
|
||||
let h = hash_value(&value.raw());
|
||||
MerkleTree::verify(MAX_DEPTH, root, proof, &RawValue::from(h), &EMPTY_VALUE)
|
||||
Ok(MerkleTree::verify(
|
||||
MAX_DEPTH,
|
||||
root,
|
||||
proof,
|
||||
&RawValue::from(h),
|
||||
&EMPTY_VALUE,
|
||||
)?)
|
||||
}
|
||||
pub fn verify_nonexistence(root: Hash, proof: &MerkleProof, value: &Value) -> Result<()> {
|
||||
let h = hash_value(&value.raw());
|
||||
MerkleTree::verify_nonexistence(MAX_DEPTH, root, proof, &RawValue::from(h))
|
||||
Ok(MerkleTree::verify_nonexistence(
|
||||
MAX_DEPTH,
|
||||
root,
|
||||
proof,
|
||||
&RawValue::from(h),
|
||||
)?)
|
||||
}
|
||||
pub fn set(&self) -> &HashSet<Value> {
|
||||
&self.set
|
||||
|
|
@ -217,9 +236,9 @@ impl Array {
|
|||
self.mt.root()
|
||||
}
|
||||
pub fn get(&self, i: usize) -> Result<&Value> {
|
||||
self.array
|
||||
.get(i)
|
||||
.ok_or_else(|| anyhow!("index {} out of bounds 0..{}", i, self.array.len()))
|
||||
self.array.get(i).ok_or_else(|| {
|
||||
Error::custom(format!("index {} out of bounds 0..{}", i, self.array.len()))
|
||||
})
|
||||
}
|
||||
pub fn prove(&self, i: usize) -> Result<(&Value, MerkleProof)> {
|
||||
let (_, mtp) = self.mt.prove(&RawValue::from(i as i64))?;
|
||||
|
|
@ -227,13 +246,13 @@ impl Array {
|
|||
Ok((value, mtp))
|
||||
}
|
||||
pub fn verify(root: Hash, proof: &MerkleProof, i: usize, value: &Value) -> Result<()> {
|
||||
MerkleTree::verify(
|
||||
Ok(MerkleTree::verify(
|
||||
MAX_DEPTH,
|
||||
root,
|
||||
proof,
|
||||
&RawValue::from(i as i64),
|
||||
&value.raw(),
|
||||
)
|
||||
)?)
|
||||
}
|
||||
pub fn array(&self) -> &[Value] {
|
||||
&self.array
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use std::{fmt, iter, sync::Arc};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use plonky2::field::types::Field;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::middleware::{
|
||||
hash_fields, Hash, Key, NativePredicate, Params, ToFields, Value, F, HASH_SIZE,
|
||||
hash_fields, Error, Hash, Key, NativePredicate, Params, Result, ToFields, Value, F, HASH_SIZE,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
|
||||
|
|
@ -217,7 +216,11 @@ impl CustomPredicate {
|
|||
args_len: usize,
|
||||
) -> Result<Self> {
|
||||
if statements.len() > params.max_custom_predicate_arity {
|
||||
return Err(anyhow!("Custom predicate depends on too many statements"));
|
||||
return Err(Error::max_length(
|
||||
"statements.len".to_string(),
|
||||
statements.len(),
|
||||
params.max_custom_predicate_arity,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
|
|
@ -394,7 +397,6 @@ impl fmt::Display for Predicate {
|
|||
mod tests {
|
||||
use std::{array, sync::Arc};
|
||||
|
||||
use anyhow::Result;
|
||||
use plonky2::field::goldilocks_field::GoldilocksField;
|
||||
|
||||
use super::*;
|
||||
|
|
|
|||
71
src/middleware/error.rs
Normal file
71
src/middleware/error.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
//! middleware errors
|
||||
|
||||
use std::{backtrace::Backtrace, fmt::Debug};
|
||||
|
||||
use crate::middleware::{Operation, Statement, StatementArg};
|
||||
|
||||
pub type Result<T, E = Error> = core::result::Result<T, E>;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum MiddlewareInnerError {
|
||||
#[error("incorrect statement args")]
|
||||
IncorrectStatementArgs,
|
||||
#[error("invalid deduction: {0:?} ⇏ {1:#}")]
|
||||
InvalidDeduction(Operation, Statement),
|
||||
#[error("statement argument {0:?} should be a {1}")]
|
||||
InvalidStatementArg(StatementArg, String),
|
||||
#[error("{0} {1} is over the limit {2}")]
|
||||
MaxLength(String, usize, usize),
|
||||
#[error("{0} amount of {1} should be {1} but it's {2}")]
|
||||
DiffAmount(String, String, usize, usize),
|
||||
// Other
|
||||
#[error("{0}")]
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("Inner: {inner}\n{backtrace}")]
|
||||
Inner {
|
||||
inner: Box<MiddlewareInnerError>,
|
||||
backtrace: Box<Backtrace>,
|
||||
},
|
||||
#[error(transparent)]
|
||||
Tree(#[from] crate::backends::plonky2::primitives::merkletree::error::TreeError),
|
||||
}
|
||||
|
||||
impl Debug for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! new {
|
||||
($inner:expr) => {
|
||||
Error::Inner {
|
||||
inner: Box::new($inner),
|
||||
backtrace: Box::new(Backtrace::capture()),
|
||||
}
|
||||
};
|
||||
}
|
||||
use MiddlewareInnerError::*;
|
||||
impl Error {
|
||||
pub(crate) fn incorrect_statements_args() -> Self {
|
||||
new!(IncorrectStatementArgs)
|
||||
}
|
||||
pub(crate) fn invalid_deduction(op: Operation, st: Statement) -> Self {
|
||||
new!(InvalidDeduction(op, st))
|
||||
}
|
||||
pub(crate) fn invalid_statement_arg(st_arg: StatementArg, v: String) -> Self {
|
||||
new!(InvalidStatementArg(st_arg, v))
|
||||
}
|
||||
pub(crate) fn max_length(obj: String, found: usize, expect: usize) -> Self {
|
||||
new!(MaxLength(obj, found, expect))
|
||||
}
|
||||
pub(crate) fn diff_amount(obj: String, unit: String, expect: usize, found: usize) -> Self {
|
||||
new!(DiffAmount(obj, unit, expect, found))
|
||||
}
|
||||
pub(crate) fn custom(s: String) -> Self {
|
||||
new!(Custom(s))
|
||||
}
|
||||
}
|
||||
|
|
@ -8,21 +8,21 @@ use std::{
|
|||
hash,
|
||||
};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use containers::{Array, Dictionary, Set};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub mod containers;
|
||||
mod custom;
|
||||
mod error;
|
||||
mod operation;
|
||||
pub mod serialization;
|
||||
mod statement;
|
||||
use std::{any::Any, collections::HashMap, fmt};
|
||||
|
||||
use anyhow::Result;
|
||||
pub use basetypes::*;
|
||||
pub use custom::*;
|
||||
use dyn_clone::DynClone;
|
||||
pub use error::*;
|
||||
pub use operation::*;
|
||||
use serialization::*;
|
||||
pub use statement::*;
|
||||
|
|
@ -126,22 +126,25 @@ impl From<PodType> for TypedValue {
|
|||
}
|
||||
|
||||
impl TryFrom<&TypedValue> for i64 {
|
||||
type Error = anyhow::Error;
|
||||
type Error = Error;
|
||||
fn try_from(v: &TypedValue) -> std::result::Result<Self, Self::Error> {
|
||||
if let TypedValue::Int(n) = v {
|
||||
Ok(*n)
|
||||
} else {
|
||||
Err(anyhow!("Value not an int"))
|
||||
Err(Error::custom("Value not an int".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<TypedValue> for Key {
|
||||
type Error = anyhow::Error;
|
||||
type Error = Error;
|
||||
fn try_from(tv: TypedValue) -> Result<Self> {
|
||||
match tv {
|
||||
TypedValue::String(s) => Ok(Key::new(s)),
|
||||
_ => Err(anyhow!("Value {} cannot be converted to a key.", tv)),
|
||||
_ => Err(Error::custom(format!(
|
||||
"Value {} cannot be converted to a key.",
|
||||
tv
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -367,20 +370,31 @@ impl Value {
|
|||
match &self.typed() {
|
||||
TypedValue::Array(a) => match key.typed() {
|
||||
TypedValue::Int(i) if i >= &0 => a.prove((*i) as usize),
|
||||
_ => Err(anyhow!("Invalid key {} for container {}.", key, self))?,
|
||||
_ => Err(Error::custom(format!(
|
||||
"Invalid key {} for container {}.",
|
||||
key, self
|
||||
)))?,
|
||||
},
|
||||
TypedValue::Dictionary(d) => d.prove(&key.typed().clone().try_into()?),
|
||||
TypedValue::Set(s) => Ok((key, s.prove(key)?)),
|
||||
_ => Err(anyhow!("Invalid container value {}", self.typed())),
|
||||
_ => Err(Error::custom(format!(
|
||||
"Invalid container value {}",
|
||||
self.typed()
|
||||
))),
|
||||
}
|
||||
}
|
||||
/// Determines Merkle non-existence proof for `key` in `self` (if applicable).
|
||||
pub(crate) fn prove_nonexistence<'a>(&'a self, key: &'a Value) -> Result<MerkleProof> {
|
||||
match &self.typed() {
|
||||
TypedValue::Array(_) => Err(anyhow!("Arrays do not support `NotContains` operation.")),
|
||||
TypedValue::Array(_) => Err(Error::custom(
|
||||
"Arrays do not support `NotContains` operation.".to_string(),
|
||||
)),
|
||||
TypedValue::Dictionary(d) => d.prove_nonexistence(&key.typed().clone().try_into()?),
|
||||
TypedValue::Set(s) => s.prove_nonexistence(key),
|
||||
_ => Err(anyhow!("Invalid container value {}", self.typed())),
|
||||
_ => Err(Error::custom(format!(
|
||||
"Invalid container value {}",
|
||||
self.typed()
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -654,8 +668,10 @@ impl Params {
|
|||
}
|
||||
}
|
||||
|
||||
pub type DynError = dyn std::error::Error + Send + Sync;
|
||||
|
||||
pub trait Pod: fmt::Debug + DynClone + Any {
|
||||
fn verify(&self) -> Result<()>;
|
||||
fn verify(&self) -> Result<(), Box<DynError>>;
|
||||
fn id(&self) -> PodId;
|
||||
fn pub_statements(&self) -> Vec<Statement>;
|
||||
/// Extract key-values from ValueOf public statements
|
||||
|
|
@ -683,7 +699,11 @@ pub trait Pod: fmt::Debug + DynClone + Any {
|
|||
dyn_clone::clone_trait_object!(Pod);
|
||||
|
||||
pub trait PodSigner {
|
||||
fn sign(&mut self, params: &Params, kvs: &HashMap<Key, Value>) -> Result<Box<dyn Pod>>;
|
||||
fn sign(
|
||||
&mut self,
|
||||
params: &Params,
|
||||
kvs: &HashMap<Key, Value>,
|
||||
) -> Result<Box<dyn Pod>, Box<DynError>>;
|
||||
}
|
||||
|
||||
/// This is a filler type that fulfills the Pod trait and always verifies. It's empty. This
|
||||
|
|
@ -692,7 +712,7 @@ pub trait PodSigner {
|
|||
pub struct NonePod {}
|
||||
|
||||
impl Pod for NonePod {
|
||||
fn verify(&self) -> Result<()> {
|
||||
fn verify(&self) -> Result<(), Box<DynError>> {
|
||||
Ok(())
|
||||
}
|
||||
fn id(&self) -> PodId {
|
||||
|
|
@ -718,7 +738,11 @@ pub struct MainPodInputs<'a> {
|
|||
}
|
||||
|
||||
pub trait PodProver {
|
||||
fn prove(&mut self, params: &Params, inputs: MainPodInputs) -> Result<Box<dyn Pod>>;
|
||||
fn prove(
|
||||
&mut self,
|
||||
params: &Params,
|
||||
inputs: MainPodInputs,
|
||||
) -> Result<Box<dyn Pod>, Box<DynError>>;
|
||||
}
|
||||
|
||||
pub trait ToFields {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::{fmt, iter, sync::Arc};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use log::error;
|
||||
use plonky2::field::types::Field;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -8,9 +7,9 @@ use serde::{Deserialize, Serialize};
|
|||
use crate::{
|
||||
backends::plonky2::primitives::merkletree::MerkleProof,
|
||||
middleware::{
|
||||
custom::KeyOrWildcard, AnchoredKey, CustomPredicateBatch, CustomPredicateRef,
|
||||
NativePredicate, Params, Predicate, Statement, StatementArg, StatementTmplArg, ToFields,
|
||||
Wildcard, WildcardValue, F, SELF,
|
||||
custom::KeyOrWildcard, AnchoredKey, CustomPredicateBatch, CustomPredicateRef, Error,
|
||||
NativePredicate, Params, Predicate, Result, Statement, StatementArg, StatementTmplArg,
|
||||
ToFields, Wildcard, WildcardValue, F, SELF,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -253,11 +252,10 @@ impl Operation {
|
|||
Self::ProductOf(s1, s2, s3)
|
||||
}
|
||||
(NO::MaxOf, (Some(s1), Some(s2), Some(s3)), OA::None, 3) => Self::MaxOf(s1, s2, s3),
|
||||
_ => Err(anyhow!(
|
||||
_ => Err(Error::custom(format!(
|
||||
"Ill-formed operation {:?} with arguments {:?}.",
|
||||
op_code,
|
||||
args
|
||||
))?,
|
||||
op_code, args
|
||||
)))?,
|
||||
},
|
||||
OperationType::Custom(cpr) => Self::Custom(cpr, args.to_vec()),
|
||||
})
|
||||
|
|
@ -320,10 +318,9 @@ impl Operation {
|
|||
{
|
||||
check_custom_pred(params, batch, *index, args, s_args)
|
||||
}
|
||||
_ => Err(anyhow!(
|
||||
"Invalid deduction: {:?} ⇏ {:#}",
|
||||
self,
|
||||
output_statement
|
||||
_ => Err(Error::invalid_deduction(
|
||||
self.clone(),
|
||||
output_statement.clone(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
@ -386,17 +383,19 @@ fn check_custom_pred(
|
|||
) -> Result<bool> {
|
||||
let pred = &batch.predicates[index];
|
||||
if pred.statements.len() != args.len() {
|
||||
return Err(anyhow!(
|
||||
"Custom predicate operation needs {} statements but has {}.",
|
||||
return Err(Error::diff_amount(
|
||||
"custom predicate operation".to_string(),
|
||||
"statements".to_string(),
|
||||
pred.statements.len(),
|
||||
args.len()
|
||||
args.len(),
|
||||
));
|
||||
}
|
||||
if pred.args_len != s_args.len() {
|
||||
return Err(anyhow!(
|
||||
"Custom predicate statement needs {} args but has {}.",
|
||||
return Err(Error::diff_amount(
|
||||
"custom predicate statement".to_string(),
|
||||
"args".to_string(),
|
||||
pred.args_len,
|
||||
s_args.len()
|
||||
s_args.len(),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
use std::{fmt, iter};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use plonky2::field::types::Field;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum_macros::FromRepr;
|
||||
|
||||
use crate::middleware::{
|
||||
AnchoredKey, CustomPredicateRef, Key, Params, PodId, Predicate, RawValue, ToFields, Value, F,
|
||||
VALUE_SIZE,
|
||||
AnchoredKey, CustomPredicateRef, Error, Key, Params, PodId, Predicate, RawValue, Result,
|
||||
ToFields, Value, F, VALUE_SIZE,
|
||||
};
|
||||
|
||||
// TODO: Maybe store KEY_SIGNER and KEY_TYPE as Key with lazy_static
|
||||
|
|
@ -152,7 +151,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::ValueOf(a0, v1))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::Equal) => {
|
||||
|
|
@ -161,7 +160,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::Equal(a0, a1))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::NotEqual) => {
|
||||
|
|
@ -170,7 +169,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::NotEqual(a0, a1))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::Gt) => {
|
||||
|
|
@ -179,7 +178,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::Gt(a0, a1))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::Lt) => {
|
||||
|
|
@ -188,7 +187,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::Lt(a0, a1))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::Contains) => {
|
||||
|
|
@ -197,7 +196,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::Contains(a0, a1, a2))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::NotContains) => {
|
||||
|
|
@ -206,7 +205,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::NotContains(a0, a1))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::SumOf) => {
|
||||
|
|
@ -215,7 +214,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::SumOf(a0, a1, a2))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::ProductOf) => {
|
||||
|
|
@ -224,7 +223,7 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::ProductOf(a0, a1, a2))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(NativePredicate::MaxOf) => {
|
||||
|
|
@ -233,17 +232,17 @@ impl Statement {
|
|||
{
|
||||
Ok(Self::MaxOf(a0, a1, a2))
|
||||
} else {
|
||||
Err(anyhow!("Incorrect statement args"))
|
||||
Err(Error::incorrect_statements_args())
|
||||
}
|
||||
}
|
||||
Native(np) => Err(anyhow!("Predicate {:?} is syntax sugar", np)),
|
||||
Native(np) => Err(Error::custom(format!("Predicate {:?} is syntax sugar", np))),
|
||||
BatchSelf(_) => unreachable!(),
|
||||
Custom(cpr) => {
|
||||
let v_args: Result<Vec<WildcardValue>> = args
|
||||
.iter()
|
||||
.map(|x| match x {
|
||||
StatementArg::WildcardLiteral(v) => Ok(v.clone()),
|
||||
_ => Err(anyhow!("Incorrect statement args")),
|
||||
_ => Err(Error::incorrect_statements_args()),
|
||||
})
|
||||
.collect();
|
||||
Ok(Self::Custom(cpr, v_args?))
|
||||
|
|
@ -302,13 +301,19 @@ impl StatementArg {
|
|||
pub fn literal(&self) -> Result<Value> {
|
||||
match self {
|
||||
Self::Literal(value) => Ok(value.clone()),
|
||||
_ => Err(anyhow!("Statement argument {:?} is not a literal.", self)),
|
||||
_ => Err(Error::invalid_statement_arg(
|
||||
self.clone(),
|
||||
"literal".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
pub fn key(&self) -> Result<AnchoredKey> {
|
||||
match self {
|
||||
Self::Key(ak) => Ok(ak.clone()),
|
||||
_ => Err(anyhow!("Statement argument {:?} is not a key.", self)),
|
||||
_ => Err(Error::invalid_statement_arg(
|
||||
self.clone(),
|
||||
"key".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue