diff --git a/src/json.rs b/src/json.rs index 03e08c40a..5476f9667 100644 --- a/src/json.rs +++ b/src/json.rs @@ -1,7 +1,5 @@ use super::prelude::*; -use crate::sdk; -use crate::types::ERR_FAILED_PARSE; use alloc::collections::BTreeMap; use core::convert::From; use rjson::{Array, Null, Object, Value}; @@ -15,73 +13,99 @@ pub enum JsonValue { Object(BTreeMap), } +pub enum JsonError { + NotJsonType, + MissingValue, + InvalidU8, + InvalidU64, + InvalidU128, + InvalidBool, + InvalidString, + InvalidArray, +} + pub struct JsonArray(Vec); pub struct JsonObject(BTreeMap); impl JsonValue { #[allow(dead_code)] - pub fn string(&self, key: &str) -> Result { + pub fn string(&self, key: &str) -> Result { match self { - JsonValue::Object(o) => match o.get(key).ok_or(())? { + JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { JsonValue::String(s) => Ok(s.into()), - _ => Err(()), + _ => Err(JsonError::InvalidString), }, - _ => Err(()), + _ => Err(JsonError::NotJsonType), } } #[allow(dead_code)] - pub fn u64(&self, key: &str) -> Result { + pub fn u64(&self, key: &str) -> Result { match self { - JsonValue::Object(o) => match o.get(key).ok_or(())? { + JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { JsonValue::Number(n) => Ok(*n as u64), - _ => Err(()), + _ => Err(JsonError::InvalidU64), }, - _ => Err(()), + _ => Err(JsonError::NotJsonType), } } #[allow(dead_code)] - pub fn u128(&self, key: &str) -> Result { + pub fn u128(&self, key: &str) -> Result { match self { - JsonValue::Object(o) => match o.get(key).ok_or(())? { + JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { JsonValue::Number(n) => Ok(*n as u128), - _ => Err(()), + _ => Err(JsonError::InvalidU128), }, - _ => Err(()), + _ => Err(JsonError::NotJsonType), } } #[allow(dead_code)] - pub fn bool(&self, key: &str) -> Result { + pub fn bool(&self, key: &str) -> Result { match self { - JsonValue::Object(o) => match o.get(key).ok_or(())? { + JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { JsonValue::Bool(n) => Ok(*n), - _ => Err(()), + _ => Err(JsonError::InvalidBool), }, - _ => Err(()), + _ => Err(JsonError::NotJsonType), } } #[allow(dead_code)] - pub fn parse_u8(v: &JsonValue) -> u8 { + pub fn parse_u8(v: &JsonValue) -> Result { match v { - JsonValue::Number(n) => *n as u8, - _ => sdk::panic_utf8(ERR_FAILED_PARSE.as_bytes()), + JsonValue::Number(n) => Ok(*n as u8), + _ => Err(JsonError::InvalidU8), } } #[allow(dead_code)] - pub fn array(&self, key: &str, call: F) -> Result, ()> + pub fn array(&self, key: &str, call: F) -> Result, JsonError> where F: FnMut(&JsonValue) -> T, { match self { - JsonValue::Object(o) => match o.get(key).ok_or(())? { + JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { JsonValue::Array(arr) => Ok(arr.iter().map(call).collect()), - _ => Err(()), + _ => Err(JsonError::InvalidArray), }, - _ => Err(()), + _ => Err(JsonError::NotJsonType), + } + } +} + +impl AsRef<[u8]> for JsonError { + fn as_ref(&self) -> &[u8] { + match self { + Self::NotJsonType => b"ERR_NOT_A_JSON_TYPE", + Self::MissingValue => b"ERR_JSON_MISSING_VALUE", + Self::InvalidU8 => b"ERR_FAILED_PARSE_U8", + Self::InvalidU64 => b"ERR_FAILED_PARSE_U64", + Self::InvalidU128 => b"ERR_FAILED_PARSE_U128", + Self::InvalidBool => b"ERR_FAILED_PARSE_BOOL", + Self::InvalidString => b"ERR_FAILED_PARSE_STRING", + Self::InvalidArray => b"ERR_FAILED_PARSE_ARRAY", } } } diff --git a/src/lib.rs b/src/lib.rs index 293ad0658..18fa892bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,9 @@ mod contract { use crate::prelude::{Address, H256, U256}; use crate::sdk; use crate::storage::{bytes_to_key, KeyPrefix}; - use crate::types::{near_account_to_evm_address, u256_to_arr, ERR_FAILED_PARSE}; + use crate::types::{ + near_account_to_evm_address, u256_to_arr, SdkExpect, SdkUnwrap, ERR_FAILED_PARSE, + }; const CODE_KEY: &[u8; 4] = b"CODE"; const CODE_STAGE_KEY: &[u8; 10] = b"CODE_STAGE"; @@ -514,50 +516,6 @@ mod contract { near_account_to_evm_address(&sdk::predecessor_account_id()) } - trait SdkExpect { - fn sdk_expect(self, msg: &str) -> T; - } - - impl SdkExpect for Option { - fn sdk_expect(self, msg: &str) -> T { - match self { - Some(t) => t, - None => sdk::panic_utf8(msg.as_ref()), - } - } - } - - impl SdkExpect for Result { - fn sdk_expect(self, msg: &str) -> T { - match self { - Ok(t) => t, - Err(_) => sdk::panic_utf8(msg.as_ref()), - } - } - } - - trait SdkUnwrap { - fn sdk_unwrap(self) -> T; - } - - impl SdkUnwrap for Option { - fn sdk_unwrap(self) -> T { - match self { - Some(t) => t, - None => sdk::panic_utf8("ERR_UNWRAP".as_bytes()), - } - } - } - - impl> SdkUnwrap for Result { - fn sdk_unwrap(self) -> T { - match self { - Ok(t) => t, - Err(e) => sdk::panic_utf8(e.as_ref()), - } - } - } - trait SdkProcess { fn sdk_process(self); } diff --git a/src/parameters.rs b/src/parameters.rs index 7b1831427..ecd5aa78c 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -11,11 +11,9 @@ use crate::prelude::{String, Vec}; use crate::prover::Proof; #[cfg(feature = "engine")] use crate::sdk; -#[cfg(feature = "engine")] -use crate::types::Balance; use crate::types::{AccountId, RawAddress, RawH256, RawU256}; #[cfg(feature = "engine")] -use crate::types::{EthAddress, ERR_FAILED_PARSE}; +use crate::types::{Balance, EthAddress, SdkUnwrap}; use evm::backend::Log; /// Borsh-encoded parameters for the `new` function. @@ -258,12 +256,10 @@ pub struct TransferCallCallArgs { impl From for TransferCallCallArgs { fn from(v: json::JsonValue) -> Self { Self { - receiver_id: v - .string("receiver_id") - .expect_utf8(ERR_FAILED_PARSE.as_bytes()), - amount: v.u128("amount").expect_utf8(ERR_FAILED_PARSE.as_bytes()), + receiver_id: v.string("receiver_id").sdk_unwrap(), + amount: v.u128("amount").sdk_unwrap(), memo: v.string("memo").ok(), - msg: v.string("msg").expect_utf8(ERR_FAILED_PARSE.as_bytes()), + msg: v.string("msg").sdk_unwrap(), } } } @@ -279,9 +275,7 @@ pub struct StorageBalanceOfCallArgs { impl From for StorageBalanceOfCallArgs { fn from(v: json::JsonValue) -> Self { Self { - account_id: v - .string("account_id") - .expect_utf8(ERR_FAILED_PARSE.as_bytes()), + account_id: v.string("account_id").sdk_unwrap(), } } } @@ -333,10 +327,8 @@ pub struct TransferCallArgs { impl From for TransferCallArgs { fn from(v: json::JsonValue) -> Self { Self { - receiver_id: v - .string("receiver_id") - .expect_utf8(ERR_FAILED_PARSE.as_bytes()), - amount: v.u128("amount").expect_utf8(ERR_FAILED_PARSE.as_bytes()), + receiver_id: v.string("receiver_id").sdk_unwrap(), + amount: v.u128("amount").sdk_unwrap(), memo: v.string("memo").ok(), } } @@ -367,9 +359,7 @@ pub struct BalanceOfEthCallArgs { impl From for BalanceOfCallArgs { fn from(v: json::JsonValue) -> Self { Self { - account_id: v - .string("account_id") - .expect_utf8(ERR_FAILED_PARSE.as_bytes()), + account_id: v.string("account_id").sdk_unwrap(), } } } @@ -415,13 +405,9 @@ impl ExpectUtf8 for core::result::Result { impl From for ResolveTransferCallArgs { fn from(v: json::JsonValue) -> Self { Self { - sender_id: v - .string("sender_id") - .expect_utf8(ERR_FAILED_PARSE.as_bytes()), - receiver_id: v - .string("receiver_id") - .expect_utf8(ERR_FAILED_PARSE.as_bytes()), - amount: v.u128("amount").expect_utf8(ERR_FAILED_PARSE.as_bytes()), + sender_id: v.string("sender_id").sdk_unwrap(), + receiver_id: v.string("receiver_id").sdk_unwrap(), + amount: v.u128("amount").sdk_unwrap(), } } } diff --git a/src/types.rs b/src/types.rs index 1137c6b0f..6c321cc38 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,7 +6,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; #[cfg(not(feature = "contract"))] use sha3::{Digest, Keccak256}; -#[cfg(feature = "contract")] +#[cfg(feature = "engine")] use crate::sdk; pub type AccountId = String; @@ -186,6 +186,56 @@ impl ExpectUtf8 for core::result::Result { } } +#[cfg(feature = "engine")] +pub trait SdkExpect { + fn sdk_expect(self, msg: &str) -> T; +} + +#[cfg(feature = "engine")] +impl SdkExpect for Option { + fn sdk_expect(self, msg: &str) -> T { + match self { + Some(t) => t, + None => sdk::panic_utf8(msg.as_ref()), + } + } +} + +#[cfg(feature = "engine")] +impl SdkExpect for core::result::Result { + fn sdk_expect(self, msg: &str) -> T { + match self { + Ok(t) => t, + Err(_) => sdk::panic_utf8(msg.as_ref()), + } + } +} + +#[cfg(feature = "engine")] +pub trait SdkUnwrap { + fn sdk_unwrap(self) -> T; +} + +#[cfg(feature = "engine")] +impl SdkUnwrap for Option { + fn sdk_unwrap(self) -> T { + match self { + Some(t) => t, + None => sdk::panic_utf8("ERR_UNWRAP".as_bytes()), + } + } +} + +#[cfg(feature = "engine")] +impl> SdkUnwrap for core::result::Result { + fn sdk_unwrap(self) -> T { + match self { + Ok(t) => t, + Err(e) => sdk::panic_utf8(e.as_ref()), + } + } +} + #[cfg(test)] mod tests { use super::*;