1use ink_prelude::vec::Vec;
18
19use crate::sol::{
20 SolDecode,
21 SolEncode,
22};
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub enum Abi {
27 Ink,
29 Sol,
31}
32
33#[derive(Debug, Default, Clone, Copy)]
37pub struct Ink;
38
39#[derive(Debug, Default, Clone, Copy)]
43pub struct Sol;
44
45pub trait AbiEncodeWith<Abi> {
47 fn encode_with(&self) -> Vec<u8>;
49
50 fn encode_to_slice(&self, buffer: &mut [u8]) -> usize;
52
53 fn encode_to_vec(&self, buffer: &mut Vec<u8>);
55
56 fn encode_topic<H>(&self, hasher: H) -> [u8; 32]
64 where
65 H: Fn(&[u8], &mut [u8; 32]);
66}
67
68pub trait AbiDecodeWith<Abi>: Sized {
70 type Error: core::fmt::Debug;
72
73 fn decode_with(buffer: &[u8]) -> Result<Self, Self::Error>;
75}
76
77impl<T: scale::Encode> AbiEncodeWith<Ink> for T {
78 fn encode_with(&self) -> Vec<u8> {
79 scale::Encode::encode(self)
80 }
81
82 fn encode_to_slice(&self, buffer: &mut [u8]) -> usize {
83 let mut sized_output = SizedOutput::from(buffer);
84 scale::Encode::encode_to(self, &mut sized_output);
85 sized_output.len()
86 }
87
88 fn encode_to_vec(&self, buffer: &mut Vec<u8>) {
89 scale::Encode::encode_to(self, buffer);
90 }
91
92 fn encode_topic<H>(&self, hasher: H) -> [u8; 32]
93 where
94 H: Fn(&[u8], &mut [u8; 32]),
95 {
96 let encoded = scale::Encode::encode(self);
97 let len = encoded.len();
98 let mut output = [0u8; 32];
99 if encoded.len() <= 32 {
100 output.as_mut()[0..len].copy_from_slice(&encoded);
101 } else {
102 hasher(&encoded, &mut output);
103 }
104 output
105 }
106}
107
108impl<T: scale::Decode> AbiDecodeWith<Ink> for T {
109 type Error = scale::Error;
110 fn decode_with(buffer: &[u8]) -> Result<Self, Self::Error> {
111 scale::Decode::decode(&mut &buffer[..])
112 }
113}
114
115impl<T> AbiEncodeWith<Sol> for T
116where
117 T: for<'a> SolEncode<'a>,
118{
119 fn encode_with(&self) -> Vec<u8> {
120 SolEncode::encode(self)
121 }
122
123 fn encode_to_slice(&self, buffer: &mut [u8]) -> usize {
124 SolEncode::encode_to(self, buffer)
125 }
126
127 fn encode_to_vec(&self, buffer: &mut Vec<u8>) {
128 buffer.extend(SolEncode::encode(self));
129 }
130
131 fn encode_topic<H>(&self, hasher: H) -> [u8; 32]
132 where
133 H: Fn(&[u8], &mut [u8; 32]),
134 {
135 SolEncode::encode_topic(self, hasher)
136 }
137}
138
139impl<T: SolDecode> AbiDecodeWith<Sol> for T {
140 type Error = crate::sol::Error;
141 fn decode_with(buffer: &[u8]) -> Result<Self, Self::Error> {
142 T::decode(buffer)
143 }
144}
145
146pub struct SizedOutput<'a> {
148 buffer: &'a mut [u8],
149 offset: usize,
150}
151
152impl<'a> From<&'a mut [u8]> for SizedOutput<'a> {
153 fn from(buffer: &'a mut [u8]) -> Self {
154 Self { buffer, offset: 0 }
155 }
156}
157
158#[allow(clippy::len_without_is_empty)]
159impl<'a> SizedOutput<'a> {
160 pub fn len(&self) -> usize {
162 self.offset
163 }
164}
165
166impl scale::Output for SizedOutput<'_> {
167 fn write(&mut self, bytes: &[u8]) {
168 let start = self.offset;
169 let len = bytes.len();
170 debug_assert!(
171 len <= self.buffer.len(),
172 "output buffer overflowed, encoded len is {} but buffer len is {}",
173 len,
174 self.buffer.len()
175 );
176 self.buffer[start..start.checked_add(len).unwrap()].copy_from_slice(bytes);
177 self.offset = self.offset.checked_add(len).unwrap();
178 }
179}