ink_primitives/
abi.rs

1// Copyright (C) ink! contributors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Abstractions for ABI representation and encoding/decoding.
16
17use ink_prelude::vec::Vec;
18
19use crate::sol::{
20    SolDecode,
21    SolEncode,
22};
23
24/// ABI spec for encoding/decoding contract calls.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub enum Abi {
27    /// ink! ABI spec (uses Parity's SCALE codec for input/output encode/decode).
28    Ink,
29    /// Solidity ABI encoding.
30    Sol,
31}
32
33/// Marker type for ink! ABI and SCALE encoding.
34///
35/// Used with [`AbiEncodeWith`], [`AbiDecodeWith`] and `DecodeMessageResult`.
36#[derive(Debug, Default, Clone, Copy)]
37pub struct Ink;
38
39/// Marker type for Solidity ABI.
40///
41/// Used with [`AbiEncodeWith`], [`AbiDecodeWith`] and `DecodeMessageResult`.
42#[derive(Debug, Default, Clone, Copy)]
43pub struct Sol;
44
45/// Trait for ABI-specific encoding with support for both slice and vector buffers.
46pub trait AbiEncodeWith<Abi> {
47    /// Encodes the data into a fixed-size buffer, returning the number of bytes written.
48    fn encode_to_slice(&self, buffer: &mut [u8]) -> usize;
49
50    /// Encodes the data into a dynamically resizing vector.
51    fn encode_to_vec(&self, buffer: &mut Vec<u8>);
52}
53
54/// Trait for ABI-specific decoding.
55pub trait AbiDecodeWith<Abi>: Sized {
56    /// The error type that can occur during decoding.
57    type Error: core::fmt::Debug;
58    /// Decodes the data from a buffer using the provided ABI.
59    fn decode_with(buffer: &[u8]) -> Result<Self, Self::Error>;
60}
61
62impl<T: scale::Encode> AbiEncodeWith<Ink> for T {
63    fn encode_to_slice(&self, buffer: &mut [u8]) -> usize {
64        let encoded = scale::Encode::encode(self);
65        let len = encoded.len();
66        debug_assert!(
67            len <= buffer.len(),
68            "encode scope buffer overflowed, encoded len is {} but buffer len is {}",
69            len,
70            buffer.len()
71        );
72        buffer[..len].copy_from_slice(&encoded);
73        len
74    }
75
76    fn encode_to_vec(&self, buffer: &mut Vec<u8>) {
77        scale::Encode::encode_to(self, buffer);
78    }
79}
80
81impl<T: scale::Decode> AbiDecodeWith<Ink> for T {
82    type Error = scale::Error;
83    fn decode_with(buffer: &[u8]) -> Result<Self, Self::Error> {
84        scale::Decode::decode(&mut &buffer[..])
85    }
86}
87
88impl<T> AbiEncodeWith<Sol> for T
89where
90    T: for<'a> SolEncode<'a>,
91{
92    fn encode_to_slice(&self, buffer: &mut [u8]) -> usize {
93        let encoded = T::encode(self);
94        let len = encoded.len();
95        debug_assert!(
96            len <= buffer.len(),
97            "encode scope buffer overflowed, encoded len is {} but buffer len is {}",
98            len,
99            buffer.len()
100        );
101        buffer[..len].copy_from_slice(&encoded);
102        len
103    }
104
105    fn encode_to_vec(&self, buffer: &mut Vec<u8>) {
106        buffer.extend_from_slice(&T::encode(self));
107    }
108}
109
110impl<T: SolDecode> AbiDecodeWith<Sol> for T {
111    type Error = crate::sol::Error;
112    fn decode_with(buffer: &[u8]) -> Result<Self, Self::Error> {
113        T::decode(buffer)
114    }
115}