chore(core): convenience impls for Bytes (#1421)

* chore(core): convenience impls for Bytes

* update asserts
This commit is contained in:
Matthias Seitz 2022-06-28 18:30:59 +02:00 committed by GitHub
parent f17f900d01
commit 7c6462be02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 11 deletions

View File

@ -189,18 +189,18 @@ fn can_gen_human_readable_with_structs() {
let call = BarCall { x: 1u64.into(), y: 0u64.into(), addr: Address::random() }; let call = BarCall { x: 1u64.into(), y: 0u64.into(), addr: Address::random() };
let encoded_call = contract.encode("bar", (call.x, call.y, call.addr)).unwrap(); let encoded_call = contract.encode("bar", (call.x, call.y, call.addr)).unwrap();
assert_eq!(encoded_call, call.clone().encode().into()); assert_eq!(encoded_call, call.clone().encode());
let decoded_call = BarCall::decode(encoded_call.as_ref()).unwrap(); let decoded_call = BarCall::decode(encoded_call.as_ref()).unwrap();
assert_eq!(call, decoded_call); assert_eq!(call, decoded_call);
let contract_call = SimpleContractCalls::Bar(call); let contract_call = SimpleContractCalls::Bar(call);
let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap(); let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap();
assert_eq!(contract_call, decoded_enum); assert_eq!(contract_call, decoded_enum);
assert_eq!(encoded_call, contract_call.encode().into()); assert_eq!(encoded_call, contract_call.encode());
let call = YeetCall(1u64.into(), 0u64.into(), Address::zero()); let call = YeetCall(1u64.into(), 0u64.into(), Address::zero());
let encoded_call = contract.encode("yeet", (call.0, call.1, call.2)).unwrap(); let encoded_call = contract.encode("yeet", (call.0, call.1, call.2)).unwrap();
assert_eq!(encoded_call, call.clone().encode().into()); assert_eq!(encoded_call, call.clone().encode());
let decoded_call = YeetCall::decode(encoded_call.as_ref()).unwrap(); let decoded_call = YeetCall::decode(encoded_call.as_ref()).unwrap();
assert_eq!(call, decoded_call); assert_eq!(call, decoded_call);
@ -208,7 +208,7 @@ fn can_gen_human_readable_with_structs() {
let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap(); let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap();
assert_eq!(contract_call, decoded_enum); assert_eq!(contract_call, decoded_enum);
assert_eq!(contract_call, call.into()); assert_eq!(contract_call, call.into());
assert_eq!(encoded_call, contract_call.encode().into()); assert_eq!(encoded_call, contract_call.encode());
} }
#[test] #[test]
@ -235,26 +235,26 @@ fn can_handle_overloaded_functions() {
let call = GetValueCall; let call = GetValueCall;
let encoded_call = contract.encode("getValue", ()).unwrap(); let encoded_call = contract.encode("getValue", ()).unwrap();
assert_eq!(encoded_call, call.clone().encode().into()); assert_eq!(encoded_call, call.clone().encode());
let decoded_call = GetValueCall::decode(encoded_call.as_ref()).unwrap(); let decoded_call = GetValueCall::decode(encoded_call.as_ref()).unwrap();
assert_eq!(call, decoded_call); assert_eq!(call, decoded_call);
let contract_call = SimpleContractCalls::GetValue(call); let contract_call = SimpleContractCalls::GetValue(call);
let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap(); let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap();
assert_eq!(contract_call, decoded_enum); assert_eq!(contract_call, decoded_enum);
assert_eq!(encoded_call, contract_call.encode().into()); assert_eq!(encoded_call, contract_call.encode());
let call = GetValueWithOtherValueCall { other_value: 420u64.into() }; let call = GetValueWithOtherValueCall { other_value: 420u64.into() };
let encoded_call = contract.encode_with_selector([15, 244, 201, 22], call.other_value).unwrap(); let encoded_call = contract.encode_with_selector([15, 244, 201, 22], call.other_value).unwrap();
assert_eq!(encoded_call, call.clone().encode().into()); assert_eq!(encoded_call, call.clone().encode());
let decoded_call = GetValueWithOtherValueCall::decode(encoded_call.as_ref()).unwrap(); let decoded_call = GetValueWithOtherValueCall::decode(encoded_call.as_ref()).unwrap();
assert_eq!(call, decoded_call); assert_eq!(call, decoded_call);
let contract_call = SimpleContractCalls::GetValueWithOtherValue(call); let contract_call = SimpleContractCalls::GetValueWithOtherValue(call);
let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap(); let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap();
assert_eq!(contract_call, decoded_enum); assert_eq!(contract_call, decoded_enum);
assert_eq!(encoded_call, contract_call.encode().into()); assert_eq!(encoded_call, contract_call.encode());
let call = let call =
GetValueWithOtherValueAndAddrCall { other_value: 420u64.into(), addr: Address::random() }; GetValueWithOtherValueAndAddrCall { other_value: 420u64.into(), addr: Address::random() };
@ -267,7 +267,7 @@ fn can_handle_overloaded_functions() {
let contract_call = SimpleContractCalls::GetValueWithOtherValueAndAddr(call); let contract_call = SimpleContractCalls::GetValueWithOtherValueAndAddr(call);
let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap(); let decoded_enum = SimpleContractCalls::decode(encoded_call.as_ref()).unwrap();
assert_eq!(contract_call, decoded_enum); assert_eq!(contract_call, decoded_enum);
assert_eq!(encoded_call, contract_call.encode().into()); assert_eq!(encoded_call, contract_call.encode());
let call = SetValue0Call("message".to_string()); let call = SetValue0Call("message".to_string());
let _contract_call = SimpleContractCalls::SetValue0(call); let _contract_call = SimpleContractCalls::SetValue0(call);
@ -443,7 +443,7 @@ fn can_generate_nested_types() {
let call = MyfunCall { a: a.clone() }; let call = MyfunCall { a: a.clone() };
let encoded_call = contract.encode("myfun", (a,)).unwrap(); let encoded_call = contract.encode("myfun", (a,)).unwrap();
assert_eq!(encoded_call, call.clone().encode().into()); assert_eq!(encoded_call, call.clone().encode());
let decoded_call = MyfunCall::decode(encoded_call.as_ref()).unwrap(); let decoded_call = MyfunCall::decode(encoded_call.as_ref()).unwrap();
assert_eq!(call, decoded_call); assert_eq!(call, decoded_call);
} }

View File

@ -57,6 +57,7 @@ macro_rules! impl_abi_codec {
impl_abi_codec!( impl_abi_codec!(
Vec<u8>, Vec<u8>,
Bytes, Bytes,
bytes::Bytes,
Address, Address,
bool, bool,
String, String,

View File

@ -125,6 +125,7 @@ macro_rules! impl_abi_type {
impl_abi_type!( impl_abi_type!(
Bytes => Bytes, Bytes => Bytes,
bytes::Bytes => Bytes,
Vec<u8> => Array(Box::new(ParamType::Uint(8))), Vec<u8> => Array(Box::new(ParamType::Uint(8))),
Address => Address, Address => Address,
bool => Bool, bool => Bool,

View File

@ -159,6 +159,19 @@ impl Tokenizable for Bytes {
} }
} }
impl Tokenizable for bytes::Bytes {
fn from_token(token: Token) -> Result<Self, InvalidOutputType> {
match token {
Token::Bytes(s) => Ok(s.into()),
other => Err(InvalidOutputType(format!("Expected `Bytes`, got {:?}", other))),
}
}
fn into_token(self) -> Token {
Token::Bytes(self.to_vec())
}
}
impl Tokenizable for H256 { impl Tokenizable for H256 {
fn from_token(token: Token) -> Result<Self, InvalidOutputType> { fn from_token(token: Token) -> Result<Self, InvalidOutputType> {
match token { match token {
@ -287,7 +300,7 @@ macro_rules! tokenizable_item {
tokenizable_item! { tokenizable_item! {
Token, String, Address, H256, U256, I256, U128, bool, Vec<u8>, Token, String, Address, H256, U256, I256, U128, bool, Vec<u8>,
i8, i16, i32, i64, i128, u16, u32, u64, u128, Bytes, i8, i16, i32, i64, i128, u16, u32, u64, u128, Bytes, bytes::Bytes,
} }
macro_rules! impl_tokenizable_item_tuple { macro_rules! impl_tokenizable_item_tuple {

View File

@ -2,8 +2,10 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
use thiserror::Error; use thiserror::Error;
use std::{ use std::{
borrow::Borrow,
clone::Clone, clone::Clone,
fmt::{Debug, Display, Formatter, LowerHex, Result as FmtResult}, fmt::{Debug, Display, Formatter, LowerHex, Result as FmtResult},
ops::Deref,
str::FromStr, str::FromStr,
}; };
@ -36,12 +38,45 @@ impl Bytes {
} }
} }
impl Deref for Bytes {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] {
self.as_ref()
}
}
impl AsRef<[u8]> for Bytes { impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] {
self.0.as_ref() self.0.as_ref()
} }
} }
impl Borrow<[u8]> for Bytes {
fn borrow(&self) -> &[u8] {
self.as_ref()
}
}
impl IntoIterator for Bytes {
type Item = u8;
type IntoIter = bytes::buf::IntoIter<bytes::Bytes>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a> IntoIterator for &'a Bytes {
type Item = &'a u8;
type IntoIter = core::slice::Iter<'a, u8>;
fn into_iter(self) -> Self::IntoIter {
self.as_ref().iter()
}
}
impl From<bytes::Bytes> for Bytes { impl From<bytes::Bytes> for Bytes {
fn from(src: bytes::Bytes) -> Self { fn from(src: bytes::Bytes) -> Self {
Self(src) Self(src)
@ -66,6 +101,36 @@ impl<'a, const N: usize> From<&'a [u8; N]> for Bytes {
} }
} }
impl PartialEq<[u8]> for Bytes {
fn eq(&self, other: &[u8]) -> bool {
self.as_ref() == other
}
}
impl PartialEq<Bytes> for [u8] {
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}
impl PartialEq<Vec<u8>> for Bytes {
fn eq(&self, other: &Vec<u8>) -> bool {
self.as_ref() == &other[..]
}
}
impl PartialEq<Bytes> for Vec<u8> {
fn eq(&self, other: &Bytes) -> bool {
*other == *self
}
}
impl PartialEq<bytes::Bytes> for Bytes {
fn eq(&self, other: &bytes::Bytes) -> bool {
other == self.as_ref()
}
}
#[derive(Debug, Clone, Error)] #[derive(Debug, Clone, Error)]
#[error("Failed to parse bytes: {0}")] #[error("Failed to parse bytes: {0}")]
pub struct ParseBytesError(String); pub struct ParseBytesError(String);