1use core::str::from_utf8;
2
3use super::{AbiDecoder, AbiEncoder, Error};
4use crate::{abi::Result, custom_signature::SignatureUnit, types::*};
5
6pub trait AbiType {
8 const SIGNATURE: SignatureUnit;
10 const IS_DYNAMIC: bool;
12 const HEAD_WORDS: u32;
14
15 #[must_use]
17 fn signature() -> &'static str {
18 from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
19 }
20}
21impl<T> AbiType for &T
22where
23 T: AbiType,
24{
25 const SIGNATURE: SignatureUnit = T::SIGNATURE;
26 const IS_DYNAMIC: bool = T::IS_DYNAMIC;
27 const HEAD_WORDS: u32 = T::HEAD_WORDS;
28}
29
30pub trait AbiEncode: Sized + AbiType {
32 fn enc(&self, out: &mut AbiEncoder);
33 fn abi_encode(&self) -> Vec<u8> {
34 let mut encoder = AbiEncoder::new(vec![], 0, 0);
35 encoder.encode_tail(self);
36 encoder.into_inner()
37 }
38 fn abi_encode_call(&self, selector: Bytes4) -> Vec<u8> {
39 let mut encoder = AbiEncoder::new(selector.into(), 4, 4);
40 encoder.encode_tail(self);
41 encoder.into_inner()
42 }
43}
44impl<T> AbiEncode for &T
45where
46 T: AbiEncode,
47{
48 fn enc(&self, out: &mut AbiEncoder) {
49 (*self).enc(out);
50 }
51}
52pub trait AbiEncodeZero: AbiEncode {
53 fn enc_zero(out: &mut AbiEncoder);
54}
55impl<T: Default + AbiEncode> AbiEncodeZero for T {
56 fn enc_zero(out: &mut AbiEncoder) {
57 T::default().enc(out)
58 }
59}
60
61pub trait AbiDecode: Sized + AbiType {
63 fn dec(input: &mut AbiDecoder<'_>) -> Result<Self>;
64 fn abi_decode(input: &[u8]) -> Result<Self> {
65 let mut decoder = AbiDecoder::new(input, 0)?;
66 Self::dec(&mut decoder)
67 }
68 fn abi_decode_call(input: &[u8]) -> Result<(Bytes4, Self)> {
69 let mut num = [0; 4];
70 num.copy_from_slice(&input[..4]);
71 Ok((BytesFixed(num), Self::abi_decode(&input[4..])?))
72 }
73}
74pub trait AbiDecodeZero: AbiDecode {
76 fn dec_zero(input: &mut AbiDecoder<'_>) -> Result<()>;
77}
78impl<T: Default + AbiDecode + PartialEq> AbiDecodeZero for T {
79 fn dec_zero(input: &mut AbiDecoder<'_>) -> Result<()> {
80 let value = T::dec(input)?;
81 if value != T::default() {
82 return Err(Error::InvalidRange);
83 }
84 Ok(())
85 }
86}