-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
236 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
use std::collections::BTreeMap; | ||
use std::num::NonZeroU8; | ||
|
||
use bytes::Bytes; | ||
use everscale_crypto::ed25519; | ||
use num_bigint::{BigInt, BigUint}; | ||
|
||
use super::ty::*; | ||
use crate::cell::Cell; | ||
use crate::models::IntAddr; | ||
use crate::num::Tokens; | ||
|
||
/// ABI value with name. | ||
#[derive(Debug, Clone, Eq, PartialEq)] | ||
pub struct NamedAbiValue { | ||
/// Item name. | ||
pub name: String, | ||
/// ABI value. | ||
pub value: AbiValue, | ||
} | ||
|
||
impl NamedAbiValue { | ||
/// Returns whether all values satisfy the provided types. | ||
pub fn have_types(items: &[Self], types: &[NamedAbiType]) -> bool { | ||
items.len() == types.len() | ||
&& items | ||
.iter() | ||
.zip(types.iter()) | ||
.all(|(item, t)| item.value.has_type(&t.ty)) | ||
} | ||
} | ||
|
||
/// ABI encoded value. | ||
#[derive(Debug, Clone, Eq, PartialEq)] | ||
pub enum AbiValue { | ||
/// Unsigned integer of n bits. | ||
Uint(u16, BigUint), | ||
/// Signed integer of n bits. | ||
Int(u16, BigInt), | ||
/// Variable-length unsigned integer of maximum n bytes. | ||
VarUint(NonZeroU8, BigUint), | ||
/// Variable-length signed integer of maximum n bytes. | ||
VarInt(NonZeroU8, BigInt), | ||
/// Boolean. | ||
Bool(bool), | ||
/// Tree of cells ([`Cell`]). | ||
/// | ||
/// [`Cell`]: crate::cell::Cell | ||
Cell(Cell), | ||
/// Internal address ([`IntAddr`]). | ||
/// | ||
/// [`IntAddr`]: crate::models::message::IntAddr | ||
Address(Box<IntAddr>), | ||
/// Byte array. | ||
Bytes(Bytes), | ||
/// Byte array of fixed length. | ||
FixedBytes(Bytes), | ||
/// Utf8-encoded string. | ||
String(String), | ||
/// Variable length 120-bit integer ([`Tokens`]). | ||
/// | ||
/// [`Tokens`]: crate::num::Tokens | ||
Token(Tokens), | ||
/// Product type. | ||
Tuple(Vec<NamedAbiValue>), | ||
/// Array of ABI values. | ||
Array(Box<AbiType>, Vec<Self>), | ||
/// Fixed-length array of ABI values. | ||
FixedArray(Box<AbiType>, Vec<Self>), | ||
/// Sorted dictionary of ABI values. | ||
Map( | ||
PlainAbiType, | ||
Box<AbiType>, | ||
BTreeMap<PlainAbiValue, AbiValue>, | ||
), | ||
/// Optional value. | ||
Optional(Box<AbiType>, Option<Box<Self>>), | ||
/// Value stored in a new cell. | ||
Ref(Box<Self>), | ||
} | ||
|
||
impl AbiValue { | ||
/// Returns whether this value has the same type as the provided one. | ||
pub fn has_type(&self, ty: &AbiType) -> bool { | ||
match (self, ty) { | ||
(Self::Uint(n, _), AbiType::Uint(t)) => n == t, | ||
(Self::Int(n, _), AbiType::Int(t)) => n == t, | ||
(Self::VarUint(n, _), AbiType::VarUint(t)) => n == t, | ||
(Self::VarInt(n, _), AbiType::VarInt(t)) => n == t, | ||
(Self::FixedBytes(bytes), AbiType::FixedBytes(len)) => bytes.len() == *len, | ||
(Self::Tuple(items), AbiType::Tuple(types)) => NamedAbiValue::have_types(items, types), | ||
(Self::Array(ty, _), AbiType::Array(t)) => ty == t, | ||
(Self::FixedArray(ty, items), AbiType::FixedArray(t, len)) => { | ||
items.len() == *len && ty == t | ||
} | ||
(Self::Map(key_ty, value_ty, _), AbiType::Map(k, v)) => key_ty == k && value_ty == v, | ||
(Self::Optional(ty, _), AbiType::Optional(t)) => ty == t, | ||
(Self::Ref(value), AbiType::Ref(t)) => value.has_type(t), | ||
(Self::Bool(_), AbiType::Bool) | ||
| (Self::Cell(_), AbiType::Cell) | ||
| (Self::Address(_), AbiType::Address) | ||
| (Self::Bytes(_), AbiType::Bytes) | ||
| (Self::String(_), AbiType::String) | ||
| (Self::Token(_), AbiType::Token) => true, | ||
_ => false, | ||
} | ||
} | ||
|
||
/// Returns an ABI type of the value. | ||
pub fn get_type(&self) -> AbiType { | ||
match self { | ||
AbiValue::Uint(n, _) => AbiType::Uint(*n), | ||
AbiValue::Int(n, _) => AbiType::Int(*n), | ||
AbiValue::VarUint(n, _) => AbiType::VarUint(*n), | ||
AbiValue::VarInt(n, _) => AbiType::VarInt(*n), | ||
AbiValue::Bool(_) => AbiType::Bool, | ||
AbiValue::Cell(_) => AbiType::Cell, | ||
AbiValue::Address(_) => AbiType::Address, | ||
AbiValue::Bytes(_) => AbiType::Bytes, | ||
AbiValue::FixedBytes(bytes) => AbiType::FixedBytes(bytes.len()), | ||
AbiValue::String(_) => AbiType::String, | ||
AbiValue::Token(_) => AbiType::Token, | ||
AbiValue::Tuple(items) => AbiType::Tuple( | ||
items | ||
.iter() | ||
.map(|item| NamedAbiType::new(item.name.clone(), item.value.get_type())) | ||
.collect(), | ||
), | ||
AbiValue::Array(ty, _) => AbiType::Array(ty.clone()), | ||
AbiValue::FixedArray(ty, items) => AbiType::FixedArray(ty.clone(), items.len()), | ||
AbiValue::Map(key_ty, value_ty, _) => AbiType::Map(*key_ty, value_ty.clone()), | ||
AbiValue::Optional(ty, _) => AbiType::Optional(ty.clone()), | ||
AbiValue::Ref(value) => AbiType::Ref(Box::new(value.get_type())), | ||
} | ||
} | ||
} | ||
|
||
/// ABI value which has a fixed bits representation | ||
/// and therefore can be used as a map key. | ||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] | ||
pub enum PlainAbiValue { | ||
/// Unsigned integer of n bits. | ||
Uint(u16, BigUint), | ||
/// Signed integer of n bits. | ||
Int(u16, BigInt), | ||
/// Boolean. | ||
Bool(bool), | ||
/// Internal address ([`IntAddr`]). | ||
/// | ||
/// [`IntAddr`]: crate::models::message::IntAddr | ||
Address(Box<IntAddr>), | ||
} | ||
|
||
impl PlainAbiValue { | ||
/// Returns whether this value has the same type as the provided one. | ||
pub fn has_type(&self, ty: &PlainAbiType) -> bool { | ||
match (self, ty) { | ||
(Self::Uint(n, _), PlainAbiType::Uint(t)) => n == t, | ||
(Self::Int(n, _), PlainAbiType::Int(t)) => n == t, | ||
(Self::Bool(_), PlainAbiType::Bool) | (Self::Address(_), PlainAbiType::Address) => true, | ||
_ => false, | ||
} | ||
} | ||
} | ||
|
||
impl From<PlainAbiValue> for AbiValue { | ||
fn from(value: PlainAbiValue) -> Self { | ||
match value { | ||
PlainAbiValue::Uint(n, value) => Self::Uint(n, value), | ||
PlainAbiValue::Int(n, value) => Self::Int(n, value), | ||
PlainAbiValue::Bool(value) => Self::Bool(value), | ||
PlainAbiValue::Address(value) => Self::Address(value), | ||
} | ||
} | ||
} | ||
|
||
/// ABI header value. | ||
#[derive(Debug, Clone, Eq, PartialEq)] | ||
pub enum AbiHeader { | ||
/// `time` header. | ||
Time(u64), | ||
/// `expire` header. | ||
Expire(u32), | ||
/// `pubkey` header. | ||
PublicKey(Option<Box<ed25519::PublicKey>>), | ||
} | ||
|
||
impl AbiHeader { | ||
/// Returns whether this value has the same type as the provided one. | ||
pub fn has_type(&self, ty: &AbiHeaderType) -> bool { | ||
matches!( | ||
(self, ty), | ||
(Self::Time(_), AbiHeaderType::Time) | ||
| (Self::Expire(_), AbiHeaderType::Expire) | ||
| (Self::PublicKey(_), AbiHeaderType::PublicKey) | ||
) | ||
} | ||
} |