From 6b84c789396ebf7e63855f7168ed658b0e094c58 Mon Sep 17 00:00:00 2001 From: Nicholas Rodrigues Lordello Date: Thu, 22 Jun 2023 15:29:24 +0200 Subject: [PATCH] Stop Deref Abuse --- Cargo.toml | 2 +- src/decode.rs | 2 +- src/decode/context.rs | 2 +- src/function.rs | 15 ------ src/value.rs | 115 ++++++++++++++++++++++-------------------- 5 files changed, 63 insertions(+), 73 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5f413ef..aeb61eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "solabi" -version = "0.1.0" +version = "0.1.1" authors = ["Nicholas Rodrigues Lordello "] edition = "2021" description = "Solidity ABI implementation in Rust" diff --git a/src/decode.rs b/src/decode.rs index 0ba66a8..dfedd04 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -42,7 +42,7 @@ pub fn decode_with_selector(selector: Selector, bytes: &[u8]) -> Result( where T: DecodeContext, { - decode_with_prefix(&*selector, bytes, context) + decode_with_prefix(selector.as_ref(), bytes, context) } /// ABI-decodes a value prefixed with a prefix. diff --git a/src/function.rs b/src/function.rs index e07cb8b..35caca3 100644 --- a/src/function.rs +++ b/src/function.rs @@ -10,7 +10,6 @@ use ethprim::Address; use std::{ fmt::{self, Debug, Formatter}, marker::PhantomData, - ops::{Deref, DerefMut}, }; /// A function selector type. @@ -52,20 +51,6 @@ impl From<[u8; 4]> for Selector { } } -impl Deref for Selector { - type Target = [u8; 4]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Selector { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - impl PartialEq<[u8]> for Selector { fn eq(&self, other: &[u8]) -> bool { self.as_ref() == other diff --git a/src/value.rs b/src/value.rs index 76e1aff..c91ddb8 100644 --- a/src/value.rs +++ b/src/value.rs @@ -18,7 +18,7 @@ use crate::{ use ethprim::{Address, Keccak, I256, U256}; use std::{ fmt::{self, Display, Formatter}, - ops::{Deref, Shl, Shr}, + ops::{Shl, Shr}, str::FromStr, }; @@ -123,8 +123,8 @@ impl Value { /// Casts the value to a word if it is a primitive type. pub fn to_word(&self) -> Option { match self { - Value::Int(a) => Some(a.to_word()), - Value::Uint(a) => Some(a.to_word()), + Value::Int(a) => Some(a.1.to_word()), + Value::Uint(a) => Some(a.1.to_word()), Value::Address(a) => Some(a.to_word()), Value::Bool(a) => Some(a.to_word()), Value::FixedBytes(a) => Some(a.into_word()), @@ -181,13 +181,13 @@ impl Value { }; match self { - Value::Int(a) => hasher.update(a.to_word()), - Value::Uint(a) => hasher.update(a.to_word()), + Value::Int(a) => hasher.update(a.1.to_word()), + Value::Uint(a) => hasher.update(a.1.to_word()), Value::Address(a) => hasher.update(a.to_word()), Value::Bool(a) => hasher.update(a.to_word()), Value::FixedBytes(a) => hasher.update(a.into_word()), Value::Function(a) => hasher.update(a.to_word()), - Value::FixedArray(a) | Value::Array(a) => hash_array(a, hasher), + Value::FixedArray(a) | Value::Array(a) => hash_array(a.as_slice(), hasher), Value::Bytes(a) => Bytes(&a[..]).update_hash(hasher), Value::String(a) => a.update_hash(hasher), Value::Tuple(a) => hash_array(a, hasher), @@ -267,8 +267,8 @@ struct Encodable<'a>(&'a Value); impl Encode for Encodable<'_> { fn size(&self) -> Size { match self.0 { - Value::Int(value) => value.size(), - Value::Uint(value) => value.size(), + Value::Int(value) => value.1.size(), + Value::Uint(value) => value.1.size(), Value::Address(value) => value.size(), Value::Bool(value) => value.size(), Value::FixedBytes(value) => value.1.size(), @@ -286,8 +286,8 @@ impl Encode for Encodable<'_> { fn encode(&self, encoder: &mut Encoder) { match self.0 { - Value::Int(value) => value.encode(encoder), - Value::Uint(value) => value.encode(encoder), + Value::Int(value) => value.1.encode(encoder), + Value::Uint(value) => value.1.encode(encoder), Value::Address(value) => value.encode(encoder), Value::Bool(value) => value.encode(encoder), Value::FixedBytes(value) => value.1.encode(encoder), @@ -425,11 +425,11 @@ impl ValueKind { impl Display for ValueKind { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - ValueKind::Int(bit_width) => write!(f, "int{}", **bit_width), - ValueKind::Uint(bit_width) => write!(f, "uint{}", **bit_width), + ValueKind::Int(bit_width) => write!(f, "int{}", bit_width.0), + ValueKind::Uint(bit_width) => write!(f, "uint{}", bit_width.0), ValueKind::Address => f.write_str("address"), ValueKind::Bool => f.write_str("bool"), - ValueKind::FixedBytes(len) => write!(f, "bytes{}", **len), + ValueKind::FixedBytes(len) => write!(f, "bytes{}", len.0), ValueKind::Function => f.write_str("function"), ValueKind::FixedArray(len, kind) => write!(f, "{kind}[{len}]"), ValueKind::Bytes => f.write_str("bytes"), @@ -558,6 +558,11 @@ impl BitWidth { None } } + + /// Returns the bit width as a [`u32`]. + pub fn get(self) -> u32 { + self.0 + } } impl Default for BitWidth { @@ -566,14 +571,6 @@ impl Default for BitWidth { } } -impl Deref for BitWidth { - type Target = u32; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - /// An signed integer with the specified width. /// /// This type is needed because there aren't Rust equivalents for all Solidity @@ -597,13 +594,11 @@ impl Int { pub fn bit_width(&self) -> BitWidth { self.0 } -} - -impl Deref for Int { - type Target = I256; - fn deref(&self) -> &Self::Target { - &self.1 + /// Returns the integer as a [`I256`]. The integer will be sign extended if + /// its bit width is less than 256. + pub fn get(&self) -> I256 { + self.1 } } @@ -630,13 +625,10 @@ impl Uint { pub fn bit_width(&self) -> BitWidth { self.0 } -} -impl Deref for Uint { - type Target = U256; - - fn deref(&self) -> &Self::Target { - &self.1 + /// Returns the integer as a [`U256`]. + pub fn get(&self) -> U256 { + self.1 } } @@ -666,13 +658,10 @@ impl ByteLength { _ => None, } } -} -impl Deref for ByteLength { - type Target = usize; - - fn deref(&self) -> &Self::Target { - &self.0 + /// Returns the byte length as a [`usize`]. + pub fn get(self) -> usize { + self.0 } } @@ -688,14 +677,18 @@ impl FixedBytes { pub fn new(bytes: &[u8]) -> Option { let len = ByteLength::new(bytes.len())?; let mut word = Word::default(); - word[..*len].copy_from_slice(bytes); + word[..len.0].copy_from_slice(bytes); Some(Self(len, word)) } /// Returns the byte length of the fixed bytes. pub fn byte_length(&self) -> ByteLength { - // Already verified by the constructor. - ByteLength(self.len()) + self.0 + } + + /// Returns the fixed byte value as a slice of bytes. + pub fn as_bytes(&self) -> &[u8] { + &self.1[..self.0.get()] } /// Returns the fixed bytes as a word. @@ -704,14 +697,6 @@ impl FixedBytes { } } -impl Deref for FixedBytes { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.1 - } -} - macro_rules! impl_from_byte_array_for_fixed_bytes { ($($n:literal,)*) => {$( impl From<[u8; $n]> for FixedBytes { @@ -757,14 +742,21 @@ impl Array { pub fn element_kind(&self) -> &ValueKind { &self.0 } -} -impl Deref for Array { - type Target = [Value]; - - fn deref(&self) -> &Self::Target { + /// Returns the array as a slice. + pub fn as_slice(&self) -> &[Value] { &self.1 } + + /// Returns the length of the array. + pub fn len(&self) -> usize { + self.1.len() + } + + /// Returns whether or not the array is empty. + pub fn is_empty(&self) -> bool { + self.1.is_empty() + } } // TODO(nlordell): Implement these traits. @@ -776,3 +768,16 @@ impl Deref for Array { //} // TODO(nlordell): Test this madness. + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn fixed_bytes_kind() { + assert_eq!( + Value::FixedBytes(FixedBytes::new(&[1]).unwrap()).kind(), + ValueKind::FixedBytes(ByteLength::new(1).unwrap()), + ); + } +}