Skip to content

Commit

Permalink
human readable format tool prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-marinica committed Nov 20, 2023
1 parent 9b2f741 commit b3c3bb2
Show file tree
Hide file tree
Showing 16 changed files with 270 additions and 19 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ resolver = "2"
members = [
"data/codec",
"data/codec-derive",
"data/human-readable",

"framework/base",
"framework/derive",
Expand Down
2 changes: 1 addition & 1 deletion data/codec/src/single/top_en.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
};
use alloc::vec::Vec;

pub trait TopEncode: Sized {
pub trait TopEncode {
/// Attempt to serialize the value to ouput.
fn top_encode<O>(&self, output: O) -> Result<(), EncodeError>
where
Expand Down
25 changes: 25 additions & 0 deletions data/human-readable/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "multiversx-sc-codec-human-readable"
version = "0.1.0"
edition = "2018"
publish = false

authors = ["MultiversX <[email protected]>"]
license = "GPL-3.0-only"
readme = "README.md"
repository = "https://github.com/multiversx/mx-sdk-rs"
homepage = "https://multiversx.com/"
documentation = "https://docs.multiversx.com/"
description = "Conversions from a human readable format to the multiversx-sc-codec"
keywords = ["multiversx", "wasm", "webassembly", "blockchain", "contract"]
categories = ["cryptography::cryptocurrencies", "development-tools"]

[dependencies]

[dependencies.multiversx-sc-scenario]
version = "=0.44.0"
path = "../../framework/scenario"

[dependencies.multiversx-sc-meta]
version = "=0.44.0"
path = "../../framework/meta"
57 changes: 57 additions & 0 deletions data/human-readable/src/interpret.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::{error::Error, fmt::Display};

use crate::multiversx_sc::abi::{TypeContents, TypeDescription};
use multiversx_sc_meta::abi_json::ContractAbiJson;
use multiversx_sc_scenario::num_bigint::BigUint;

use crate::{AnyValue, SingleValue::UnsignedNumber};

pub fn interpret_value_according_to_abi(
input: &str,
type_name: &str,
contract_abi: &ContractAbiJson, // TODO: will need to convert to high-level ContractAbi first, this is just a prototype
) -> Result<AnyValue, Box<dyn Error>> {
let type_description = if let Some(type_description_json) = contract_abi.types.get(type_name) {
type_description_json.to_type_description(type_name)
} else {
TypeDescription {
docs: Vec::new(),
name: type_name.to_string(),
contents: TypeContents::NotSpecified,
}
};
interpret_any_value(input, &type_description)
}

pub fn interpret_any_value(
input: &str,
type_description: &TypeDescription,
) -> Result<AnyValue, Box<dyn Error>> {
match &type_description.contents {
TypeContents::NotSpecified => interpret_single_value(input, type_description.name.as_str()),
TypeContents::Enum(_) => todo!(),
TypeContents::Struct(_) => todo!(),
TypeContents::ExplicitEnum(_) => panic!("not supported"),
}
}

fn interpret_single_value(input: &str, type_name: &str) -> Result<AnyValue, Box<dyn Error>> {
match type_name {
"BigUint" | "u64" | "u32" | "u16" | "usize" | "u8" => {
let value = input.parse::<BigUint>()?;
Ok(AnyValue::SingleValue(UnsignedNumber(value)))
},
_ => Err(Box::new(InterpretError("unknown type"))),
}
}

#[derive(Debug)]
pub struct InterpretError(&'static str);

impl Display for InterpretError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}

impl Error for InterpretError {}
6 changes: 6 additions & 0 deletions data/human-readable/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
mod interpret;
mod value;

use multiversx_sc_scenario::multiversx_sc;
pub use interpret::*;
pub use value::*;
39 changes: 39 additions & 0 deletions data/human-readable/src/value/any_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use multiversx_sc_scenario::multiversx_sc::codec::{
EncodeErrorHandler, NestedEncode, NestedEncodeOutput, TopEncode, TopEncodeOutput,
};

use crate::{EnumVariant, SingleValue, StructValue};

pub enum AnyValue {
SingleValue(SingleValue),
Struct(StructValue),
Enum(Box<EnumVariant>),
}

impl NestedEncode for AnyValue {
fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
where
O: NestedEncodeOutput,
H: EncodeErrorHandler,
{
match self {
AnyValue::SingleValue(sv) => sv.dep_encode_or_handle_err(dest, h),
AnyValue::Struct(s) => s.dep_encode_or_handle_err(dest, h),
AnyValue::Enum(_) => todo!(),
}
}
}

impl TopEncode for AnyValue {
fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
where
O: TopEncodeOutput,
H: EncodeErrorHandler,
{
match self {
AnyValue::SingleValue(sv) => sv.top_encode_or_handle_err(output, h),
AnyValue::Struct(s) => s.top_encode_or_handle_err(output, h),
AnyValue::Enum(_) => todo!(),
}
}
}
6 changes: 6 additions & 0 deletions data/human-readable/src/value/enum_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use crate::AnyValue;

pub struct EnumVariant {
pub discriminant: usize,
pub value: AnyValue,
}
9 changes: 9 additions & 0 deletions data/human-readable/src/value/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod any_value;
mod enum_value;
mod single_value;
mod struct_value;

pub use any_value::*;
pub use enum_value::*;
pub use single_value::*;
pub use struct_value::*;
41 changes: 41 additions & 0 deletions data/human-readable/src/value/single_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use multiversx_sc_scenario::multiversx_sc::codec::{
num_bigint::{BigInt, BigUint},
EncodeErrorHandler, NestedEncode, NestedEncodeOutput, TopEncode, TopEncodeOutput,
};

pub enum SingleValue {
UnsignedNumber(BigUint),
SignedNumber(BigInt),
Bytes(Box<[u8]>),
Bool(bool),
}

impl NestedEncode for SingleValue {
fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
where
O: NestedEncodeOutput,
H: EncodeErrorHandler,
{
match self {
SingleValue::UnsignedNumber(bu) => bu.dep_encode_or_handle_err(dest, h),
SingleValue::SignedNumber(bi) => bi.dep_encode_or_handle_err(dest, h),
SingleValue::Bytes(bytes) => bytes.dep_encode_or_handle_err(dest, h),
SingleValue::Bool(b) => b.dep_encode_or_handle_err(dest, h),
}
}
}

impl TopEncode for SingleValue {
fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
where
O: TopEncodeOutput,
H: EncodeErrorHandler,
{
match self {
SingleValue::UnsignedNumber(bu) => bu.top_encode_or_handle_err(output, h),
SingleValue::SignedNumber(bi) => bi.top_encode_or_handle_err(output, h),
SingleValue::Bytes(bytes) => bytes.top_encode_or_handle_err(output, h),
SingleValue::Bool(b) => b.top_encode_or_handle_err(output, h),
}
}
}
38 changes: 38 additions & 0 deletions data/human-readable/src/value/struct_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use multiversx_sc_scenario::multiversx_sc::codec::{
EncodeErrorHandler, NestedEncode, NestedEncodeOutput, TopEncode, TopEncodeOutput,
};

use crate::AnyValue;

pub struct StructValue(Vec<StructField>);

pub struct StructField {
pub name: String,
pub value: AnyValue,
}

impl NestedEncode for StructValue {
fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
where
O: NestedEncodeOutput,
H: EncodeErrorHandler,
{
for field in &self.0 {
field.value.dep_encode_or_handle_err(dest, h)?;
}
Ok(())
}
}

impl TopEncode for StructValue {
fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
where
O: TopEncodeOutput,
H: EncodeErrorHandler,
{
let mut buffer = output.start_nested_encode();
self.dep_encode_or_handle_err(&mut buffer, h)?;
output.finalize_nested_encode(buffer);
Ok(())
}
}
21 changes: 21 additions & 0 deletions data/human-readable/tests/single_value_basic_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use multiversx_sc_codec_human_readable::interpret_value_according_to_abi;
use multiversx_sc_meta::abi_json::{deserialize_abi_from_json, ContractAbiJson};
use multiversx_sc_scenario::multiversx_sc::codec::top_encode_to_vec_u8;

const TEST_ABI_JSON: &str = r#"{
"name": "Test",
"endpoints": [],
"events": [],
"esdtAttributes": [],
"hasCallback": false,
"types": {}
}"#;

#[test]
fn test_display_unsigned() {
let abi_json: ContractAbiJson = deserialize_abi_from_json(TEST_ABI_JSON).unwrap();

let result = interpret_value_according_to_abi("123", "BigUint", &abi_json).unwrap();
let serialized = top_encode_to_vec_u8(&result).unwrap();
assert_eq!(serialized, vec![123]);
}
18 changes: 9 additions & 9 deletions framework/base/src/contract_base/wrappers/blockchain_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ where
}
}

#[deprecated(since = "0.41.0", note = "Please use method `get_caller` instead.")]
#[deprecated(since = "0.44.0", note = "Please use method `get_caller` instead.")]
#[cfg(feature = "alloc")]
#[inline]
pub fn get_caller_legacy(&self) -> crate::types::Address {
Expand All @@ -53,7 +53,7 @@ where
ManagedAddress::from_handle(handle)
}

#[deprecated(since = "0.41.0", note = "Please use method `get_sc_address` instead.")]
#[deprecated(since = "0.44.0", note = "Please use method `get_sc_address` instead.")]
#[cfg(feature = "alloc")]
#[inline]
pub fn get_sc_address_legacy(&self) -> crate::types::Address {
Expand Down Expand Up @@ -89,7 +89,7 @@ where
}

#[deprecated(
since = "0.41.0",
since = "0.44.0",
note = "Please use method `get_shard_of_address` instead."
)]
#[cfg(feature = "alloc")]
Expand All @@ -104,7 +104,7 @@ where
}

#[deprecated(
since = "0.41.0",
since = "0.44.0",
note = "Please use method `is_smart_contract` instead."
)]
#[cfg(feature = "alloc")]
Expand All @@ -118,7 +118,7 @@ where
A::blockchain_api_impl().is_smart_contract(address.get_handle())
}

#[deprecated(since = "0.41.0", note = "Please use method `get_balance` instead.")]
#[deprecated(since = "0.44.0", note = "Please use method `get_balance` instead.")]
#[cfg(feature = "alloc")]
#[inline]
pub fn get_balance_legacy(&self, address: &crate::types::Address) -> BigUint<A> {
Expand All @@ -145,7 +145,7 @@ where
}

#[deprecated(
since = "0.41.0",
since = "0.44.0",
note = "Please use method `get_state_root_hash` instead."
)]
#[cfg(feature = "alloc")]
Expand All @@ -161,7 +161,7 @@ where
ManagedByteArray::from_handle(handle)
}

#[deprecated(since = "0.41.0", note = "Please use method `get_tx_hash` instead.")]
#[deprecated(since = "0.44.0", note = "Please use method `get_tx_hash` instead.")]
#[cfg(feature = "alloc")]
#[inline]
pub fn get_tx_hash_legacy(&self) -> crate::types::H256 {
Expand Down Expand Up @@ -201,7 +201,7 @@ where
}

#[deprecated(
since = "0.41.0",
since = "0.44.0",
note = "Please use method `get_block_random_seed` instead."
)]
#[cfg(feature = "alloc")]
Expand Down Expand Up @@ -238,7 +238,7 @@ where
}

#[deprecated(
since = "0.41.0",
since = "0.44.0",
note = "Please use method `get_prev_block_random_seed` instead."
)]
#[cfg(feature = "alloc")]
Expand Down
Loading

0 comments on commit b3c3bb2

Please sign in to comment.