Skip to main content

tycho_types/abi/
ty.rs

1use std::borrow::Cow;
2use std::hash::Hash;
3use std::num::NonZeroU8;
4use std::str::FromStr;
5use std::sync::Arc;
6
7use serde::{Deserialize, Serialize};
8
9use super::error::{ParseAbiTypeError, ParseNamedAbiTypeError};
10use crate::abi::{AbiVersion, WithoutName};
11use crate::cell::{CellTreeStats, MAX_BIT_LEN, MAX_REF_COUNT};
12use crate::models::{IntAddr, StdAddr};
13use crate::num::Tokens;
14
15/// ABI value type with name.
16#[derive(Debug, Clone, Eq, PartialEq, Hash)]
17pub struct NamedAbiType {
18    /// Item name.
19    pub name: Arc<str>,
20    /// ABI value type.
21    pub ty: AbiType,
22}
23
24impl NamedAbiType {
25    /// Creates a named ABI type.
26    #[inline]
27    pub fn new<T>(name: T, ty: AbiType) -> Self
28    where
29        T: Into<Arc<str>>,
30    {
31        Self {
32            name: name.into(),
33            ty,
34        }
35    }
36
37    /// Creates a named ABI type with an index name (e.g. `value123`).
38    pub fn from_index(index: usize, ty: AbiType) -> Self {
39        Self::new(format!("value{index}"), ty)
40    }
41
42    /// Returns an iterator with the first-level tuple flattened.
43    ///
44    /// Can be used to pass an ABI struct as arguments to the
45    /// [`FunctionBuilder::with_inputs`] or [`FunctionBuilder::with_outputs`].
46    ///
47    /// [`FunctionBuilder::with_inputs`]: fn@crate::abi::FunctionBuilder::with_inputs
48    /// [`FunctionBuilder::with_outputs`]: fn@crate::abi::FunctionBuilder::with_outputs
49    pub fn flatten(self) -> NamedAbiTypeFlatten {
50        match self.ty {
51            AbiType::Tuple(tuple) => {
52                let mut items = tuple.to_vec();
53                items.reverse();
54                NamedAbiTypeFlatten::Tuple(items)
55            }
56            ty => NamedAbiTypeFlatten::Single(Some(NamedAbiType {
57                name: self.name,
58                ty,
59            })),
60        }
61    }
62}
63
64impl AsRef<AbiType> for NamedAbiType {
65    #[inline]
66    fn as_ref(&self) -> &AbiType {
67        &self.ty
68    }
69}
70
71impl Serialize for NamedAbiType {
72    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73    where
74        S: serde::ser::Serializer,
75    {
76        #[derive(Serialize)]
77        struct Helper<'a> {
78            name: &'a str,
79            #[serde(rename = "type", serialize_with = "collect_str")]
80            ty: DisplayAbiTypeSimple<'a>,
81            #[serde(skip_serializing_if = "Option::is_none")]
82            components: Option<&'a [NamedAbiType]>,
83        }
84
85        Helper {
86            name: &self.name,
87            ty: self.ty.display_simple(),
88            components: self.ty.components(),
89        }
90        .serialize(serializer)
91    }
92}
93
94impl<'de> Deserialize<'de> for NamedAbiType {
95    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
96    where
97        D: serde::Deserializer<'de>,
98    {
99        use serde::de::Error;
100
101        #[derive(Deserialize)]
102        struct Helper<'a> {
103            name: String,
104            #[serde(rename = "type", borrow)]
105            ty: Cow<'a, str>,
106            #[serde(default)]
107            components: Option<Vec<Helper<'a>>>,
108        }
109
110        impl TryFrom<Helper<'_>> for NamedAbiType {
111            type Error = ParseNamedAbiTypeError;
112
113            fn try_from(value: Helper<'_>) -> Result<Self, Self::Error> {
114                let mut ty = match AbiType::from_simple_str(&value.ty) {
115                    Ok(ty) => ty,
116                    Err(error) => {
117                        return Err(ParseNamedAbiTypeError::InvalidType {
118                            ty: value.ty.into(),
119                            error,
120                        });
121                    }
122                };
123
124                match (ty.components_mut(), value.components) {
125                    (Some(ty), Some(components)) => {
126                        *ty = ok!(components
127                            .into_iter()
128                            .map(Self::try_from)
129                            .collect::<Result<Arc<[_]>, _>>());
130                    }
131                    (Some(_), None) => {
132                        return Err(ParseNamedAbiTypeError::ExpectedComponents {
133                            ty: value.ty.into(),
134                        });
135                    }
136                    (None, Some(_)) => {
137                        return Err(ParseNamedAbiTypeError::UnexpectedComponents {
138                            ty: value.ty.into(),
139                        });
140                    }
141                    (None, None) => {}
142                }
143
144                Ok(Self {
145                    name: value.name.into(),
146                    ty,
147                })
148            }
149        }
150
151        let helper = ok!(<Helper as Deserialize>::deserialize(deserializer));
152        helper.try_into().map_err(Error::custom)
153    }
154}
155
156impl From<(String, AbiType)> for NamedAbiType {
157    #[inline]
158    fn from((name, ty): (String, AbiType)) -> Self {
159        Self {
160            name: name.into(),
161            ty,
162        }
163    }
164}
165
166impl<'a> From<(&'a str, AbiType)> for NamedAbiType {
167    #[inline]
168    fn from((name, ty): (&'a str, AbiType)) -> Self {
169        Self {
170            name: Arc::from(name),
171            ty,
172        }
173    }
174}
175
176impl From<(usize, AbiType)> for NamedAbiType {
177    #[inline]
178    fn from((index, ty): (usize, AbiType)) -> Self {
179        Self::from_index(index, ty)
180    }
181}
182
183impl PartialEq for WithoutName<NamedAbiType> {
184    #[inline]
185    fn eq(&self, other: &Self) -> bool {
186        WithoutName::wrap(&self.0.ty).eq(WithoutName::wrap(&other.0.ty))
187    }
188}
189
190impl Hash for WithoutName<NamedAbiType> {
191    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
192        WithoutName::wrap(&self.0.ty).hash(state);
193    }
194}
195
196impl std::borrow::Borrow<WithoutName<AbiType>> for WithoutName<NamedAbiType> {
197    fn borrow(&self) -> &WithoutName<AbiType> {
198        WithoutName::wrap(&self.0.ty)
199    }
200}
201
202/// An iterator that flattens the first-level tuple.
203#[derive(Clone)]
204pub enum NamedAbiTypeFlatten {
205    #[doc(hidden)]
206    Single(Option<NamedAbiType>),
207    #[doc(hidden)]
208    Tuple(Vec<NamedAbiType>),
209}
210
211impl Iterator for NamedAbiTypeFlatten {
212    type Item = NamedAbiType;
213
214    fn size_hint(&self) -> (usize, Option<usize>) {
215        let size = match self {
216            Self::Single(item) => item.is_some() as usize,
217            Self::Tuple(items) => items.len(),
218        };
219        (size, Some(size))
220    }
221
222    fn next(&mut self) -> Option<Self::Item> {
223        match self {
224            Self::Single(item) => item.take(),
225            Self::Tuple(items) => items.pop(),
226        }
227    }
228}
229
230/// Contract header value type.
231#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
232pub enum AbiHeaderType {
233    /// Time header type. Serialized as `uint64`.
234    Time,
235    /// Expire header type. Serialized as `uint32`.
236    Expire,
237    /// Public key type. Serialized as `optional(uint256)`.
238    PublicKey,
239}
240
241impl FromStr for AbiHeaderType {
242    type Err = ParseAbiTypeError;
243
244    fn from_str(s: &str) -> Result<Self, Self::Err> {
245        Ok(match s {
246            "time" => Self::Time,
247            "expire" => Self::Expire,
248            "pubkey" => Self::PublicKey,
249            _ => return Err(ParseAbiTypeError::UnknownType),
250        })
251    }
252}
253
254impl std::fmt::Display for AbiHeaderType {
255    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256        f.write_str(match self {
257            Self::Time => "time",
258            Self::Expire => "expire",
259            Self::PublicKey => "pubkey",
260        })
261    }
262}
263
264impl Serialize for AbiHeaderType {
265    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
266    where
267        S: serde::Serializer,
268    {
269        serializer.collect_str(&self)
270    }
271}
272
273impl<'de> Deserialize<'de> for AbiHeaderType {
274    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
275    where
276        D: serde::Deserializer<'de>,
277    {
278        use serde::de::Error;
279
280        #[derive(Deserialize)]
281        #[serde(transparent)]
282        struct Helper<'a>(#[serde(borrow)] Cow<'a, str>);
283
284        Self::from_str(&ok!(Helper::deserialize(deserializer)).0).map_err(Error::custom)
285    }
286}
287
288/// ABI value type.
289#[derive(Debug, Clone, Eq, PartialEq, Hash)]
290pub enum AbiType {
291    /// Unsigned integer of n bits.
292    Uint(u16),
293    /// Signed integer of n bits.
294    Int(u16),
295    /// Variable-length unsigned integer of maximum n bytes.
296    VarUint(NonZeroU8),
297    /// Variable-length signed integer of maximum n bytes.
298    VarInt(NonZeroU8),
299    /// Boolean.
300    Bool,
301    /// Tree of cells ([`Cell`]).
302    ///
303    /// [`Cell`]: crate::cell::Cell
304    Cell,
305    /// Internal address ([`IntAddr`]).
306    ///
307    /// [`IntAddr`]: crate::models::message::IntAddr
308    Address,
309    /// Standard internal address.
310    AddressStd,
311    /// Byte array.
312    Bytes,
313    /// Byte array of fixed length.
314    FixedBytes(usize),
315    /// Utf8-encoded string.
316    String,
317    /// Variable length 120-bit integer ([`Tokens`]).
318    ///
319    /// [`Tokens`]: crate::num::Tokens
320    Token,
321    /// Product type.
322    Tuple(Arc<[NamedAbiType]>),
323    /// Array of elements of the specified ABI type.
324    Array(Arc<Self>),
325    /// Fixed-length array of elements of the specified ABI type.
326    FixedArray(Arc<Self>, usize),
327    /// Dictionary with the specified key and value ABI types.
328    Map(PlainAbiType, Arc<Self>),
329    /// Optional type.
330    Optional(Arc<Self>),
331    /// Type stored in a new cell.
332    Ref(Arc<Self>),
333}
334
335impl AbiType {
336    /// Returns a named ABI type.
337    pub fn named<T: Into<String>>(self, name: T) -> NamedAbiType {
338        NamedAbiType {
339            name: Arc::from(name.into()),
340            ty: self,
341        }
342    }
343
344    /// Tries to convert a generic ABI type into a plain ABI type.
345    pub fn as_plain(&self) -> Option<PlainAbiType> {
346        Some(match self {
347            Self::Uint(n) => PlainAbiType::Uint(*n),
348            Self::Int(n) => PlainAbiType::Int(*n),
349            Self::Bool => PlainAbiType::Bool,
350            Self::Address => PlainAbiType::Address,
351            _ => return None,
352        })
353    }
354
355    /// Returns the maximum number of bits and refs that this type can occupy.
356    pub fn max_size(&self, abi_version: AbiVersion) -> CellTreeStats {
357        match self {
358            Self::Uint(n) | Self::Int(n) => CellTreeStats {
359                bit_count: *n as _,
360                cell_count: 0,
361            },
362            Self::VarUint(n) | Self::VarInt(n) => {
363                let value_bytes: u8 = n.get() - 1;
364                let bit_count = (8 - value_bytes.leading_zeros()) as u64 + (value_bytes as u64 * 8);
365                CellTreeStats {
366                    bit_count,
367                    cell_count: 0,
368                }
369            }
370            Self::Bool => CellTreeStats {
371                bit_count: 1,
372                cell_count: 0,
373            },
374
375            Self::FixedBytes(bytes) if abi_version >= AbiVersion::V2_4 => CellTreeStats {
376                bit_count: *bytes as u64 * 8,
377                cell_count: 0,
378            },
379            Self::Cell | Self::Bytes | Self::FixedBytes(_) | Self::String | Self::Ref(_) => {
380                CellTreeStats {
381                    bit_count: 0,
382                    cell_count: 1,
383                }
384            }
385            Self::Address => CellTreeStats {
386                bit_count: IntAddr::BITS_MAX as _,
387                cell_count: 0,
388            },
389            Self::AddressStd => CellTreeStats {
390                bit_count: StdAddr::BITS_MAX as _,
391                cell_count: 0,
392            },
393            Self::Token => CellTreeStats {
394                bit_count: Tokens::MAX_BITS as _,
395                cell_count: 0,
396            },
397            Self::Array(_) => CellTreeStats {
398                bit_count: 33,
399                cell_count: 1,
400            },
401            Self::FixedArray(..) | Self::Map(..) => CellTreeStats {
402                bit_count: 1,
403                cell_count: 1,
404            },
405            Self::Optional(ty) => {
406                let ty_size = ty.max_size(abi_version);
407                if ty_size.bit_count < MAX_BIT_LEN as u64
408                    && ty_size.cell_count < MAX_REF_COUNT as u64
409                {
410                    CellTreeStats {
411                        bit_count: 1,
412                        cell_count: 0,
413                    } + ty_size
414                } else {
415                    CellTreeStats {
416                        bit_count: 1,
417                        cell_count: 1,
418                    }
419                }
420            }
421            Self::Tuple(items) => items.iter().map(|item| item.ty.max_size(abi_version)).sum(),
422        }
423    }
424
425    /// Returns the maximum number of bits that this type can occupy.
426    pub fn max_bits(&self, abi_version: AbiVersion) -> usize {
427        self.max_size(abi_version).bit_count as usize
428    }
429
430    /// Returns the maximum number of cells that this type can occupy.
431    pub fn max_refs(&self, abi_version: AbiVersion) -> usize {
432        self.max_size(abi_version).cell_count as usize
433    }
434
435    fn components(&self) -> Option<&[NamedAbiType]> {
436        match self {
437            Self::Tuple(types) => Some(types),
438            Self::Array(ty) => ty.components(),
439            Self::FixedArray(ty, _) => ty.components(),
440            Self::Map(_, value_ty) => value_ty.components(),
441            Self::Optional(ty) => ty.components(),
442            Self::Ref(ty) => ty.components(),
443            _ => None,
444        }
445    }
446
447    pub(crate) fn components_mut(&mut self) -> Option<&mut Arc<[NamedAbiType]>> {
448        match self {
449            Self::Tuple(types) => Some(types),
450            Self::Array(ty) => Arc::make_mut(ty).components_mut(),
451            Self::FixedArray(ty, _) => Arc::make_mut(ty).components_mut(),
452            Self::Map(_, value_ty) => Arc::make_mut(value_ty).components_mut(),
453            Self::Optional(ty) => Arc::make_mut(ty).components_mut(),
454            Self::Ref(ty) => Arc::make_mut(ty).components_mut(),
455            _ => None,
456        }
457    }
458
459    /// Returns an iterator with the first-level tuple flattened.
460    ///
461    /// Can be used to pass an ABI struct as arguments to the
462    /// [`FunctionBuilder::with_unnamed_inputs`] or [`FunctionBuilder::with_unnamed_outputs`]
463    ///
464    /// [`FunctionBuilder::with_unnamed_inputs`]: fn@crate::abi::FunctionBuilder::with_unnamed_inputs
465    /// [`FunctionBuilder::with_unnamed_outputs`]: fn@crate::abi::FunctionBuilder::with_unnamed_outputs
466    pub fn flatten(self) -> AbiTypeFlatten {
467        match self {
468            AbiType::Tuple(tuple) => {
469                let mut items = tuple.to_vec();
470                items.reverse();
471                AbiTypeFlatten::Tuple(items)
472            }
473            ty => AbiTypeFlatten::Single(Some(ty)),
474        }
475    }
476
477    /// Simple `varuintN` type constructor.
478    #[inline]
479    pub fn varuint(size: u8) -> Self {
480        Self::VarUint(NonZeroU8::new(size).unwrap())
481    }
482
483    /// Simple `varintN` type constructor.
484    #[inline]
485    pub fn varint(size: u8) -> Self {
486        Self::VarInt(NonZeroU8::new(size).unwrap())
487    }
488
489    /// Simple `tuple` type constructor.
490    #[inline]
491    pub fn tuple<I, T>(values: I) -> Self
492    where
493        I: IntoIterator<Item = T>,
494        NamedAbiType: From<T>,
495    {
496        Self::Tuple(values.into_iter().map(NamedAbiType::from).collect())
497    }
498
499    /// Simple `tuple` type constructor.
500    #[inline]
501    pub fn unnamed_tuple<I>(values: I) -> Self
502    where
503        I: IntoIterator<Item = AbiType>,
504    {
505        Self::Tuple(
506            values
507                .into_iter()
508                .enumerate()
509                .map(|(i, ty)| NamedAbiType::from_index(i, ty))
510                .collect(),
511        )
512    }
513
514    /// Simple `array` type constructor.
515    #[inline]
516    pub fn array<T>(ty: T) -> Self
517    where
518        Arc<AbiType>: From<T>,
519    {
520        Self::Array(Arc::<AbiType>::from(ty))
521    }
522
523    /// Simple `fixedarrayN` type constructor.
524    #[inline]
525    pub fn fixedarray<T>(ty: T, len: usize) -> Self
526    where
527        Arc<AbiType>: From<T>,
528    {
529        Self::FixedArray(Arc::<AbiType>::from(ty), len)
530    }
531
532    /// Simple `tuple` type constructor.
533    #[inline]
534    pub fn map<V>(key_ty: PlainAbiType, value_ty: V) -> Self
535    where
536        Arc<AbiType>: From<V>,
537    {
538        Self::Map(key_ty, Arc::<AbiType>::from(value_ty))
539    }
540
541    /// Simple `optional` type constructor.
542    #[inline]
543    pub fn optional<T>(ty: T) -> Self
544    where
545        Arc<AbiType>: From<T>,
546    {
547        Self::Optional(Arc::<AbiType>::from(ty))
548    }
549
550    /// Simple `ref` type constructor.
551    #[inline]
552    pub fn reference<T>(ty: T) -> Self
553    where
554        Arc<AbiType>: From<T>,
555    {
556        Self::Ref(Arc::<AbiType>::from(ty))
557    }
558
559    pub(crate) fn from_simple_str(s: &str) -> Result<Self, ParseAbiTypeError> {
560        if let Some(arr_ty) = s.strip_suffix(']') {
561            let (ty, len) = ok!(arr_ty
562                .rsplit_once('[')
563                .ok_or(ParseAbiTypeError::InvalidArrayType));
564
565            let len = if len.is_empty() {
566                None
567            } else {
568                Some(ok!(len
569                    .parse::<usize>()
570                    .map_err(ParseAbiTypeError::InvalidArrayLength)))
571            };
572
573            let ty = ok!(Self::from_simple_str(ty).map(Arc::new));
574            return Ok(match len {
575                None => Self::Array(ty),
576                Some(len) => Self::FixedArray(ty, len),
577            });
578        }
579
580        Ok(match s {
581            "bool" => Self::Bool,
582            "cell" => Self::Cell,
583            "address" => Self::Address,
584            "address_std" => Self::AddressStd,
585            "bytes" => Self::Bytes,
586            "string" => Self::String,
587            "gram" | "token" => Self::Token,
588            "tuple" => Self::Tuple(Arc::from([].as_slice())),
589            _ => {
590                if let Some(s) = s.strip_prefix("uint") {
591                    Self::Uint(ok!(s
592                        .parse::<u16>()
593                        .map_err(ParseAbiTypeError::InvalidBitLen)))
594                } else if let Some(s) = s.strip_prefix("int") {
595                    Self::Int(ok!(s
596                        .parse::<u16>()
597                        .map_err(ParseAbiTypeError::InvalidBitLen)))
598                } else if let Some(s) = s.strip_prefix("varuint") {
599                    Self::VarUint(ok!(s
600                        .parse::<NonZeroU8>()
601                        .map_err(ParseAbiTypeError::InvalidByteLen)))
602                } else if let Some(s) = s.strip_prefix("varint") {
603                    Self::VarInt(ok!(s
604                        .parse::<NonZeroU8>()
605                        .map_err(ParseAbiTypeError::InvalidByteLen)))
606                } else if let Some(s) = s.strip_prefix("fixedbytes") {
607                    Self::FixedBytes(ok!(s
608                        .parse::<usize>()
609                        .map_err(ParseAbiTypeError::InvalidByteLen)))
610                } else if let Some(s) = s.strip_prefix("map(") {
611                    let s = ok!(s
612                        .strip_suffix(')')
613                        .ok_or(ParseAbiTypeError::UnterminatedInnerType));
614                    let (key_ty, value_ty) = ok!(s
615                        .split_once(',')
616                        .ok_or(ParseAbiTypeError::ValueTypeNotFound));
617
618                    Self::Map(
619                        ok!(PlainAbiType::from_str(key_ty)),
620                        ok!(Self::from_simple_str(value_ty).map(Arc::new)),
621                    )
622                } else if let Some(s) = s.strip_prefix("optional(") {
623                    let s = ok!(s
624                        .strip_suffix(')')
625                        .ok_or(ParseAbiTypeError::UnterminatedInnerType));
626
627                    Self::Optional(ok!(Self::from_simple_str(s).map(Arc::new)))
628                } else if let Some(s) = s.strip_prefix("ref(") {
629                    let s = ok!(s
630                        .strip_suffix(')')
631                        .ok_or(ParseAbiTypeError::UnterminatedInnerType));
632
633                    Self::Ref(ok!(Self::from_simple_str(s).map(Arc::new)))
634                } else {
635                    return Err(ParseAbiTypeError::UnknownType);
636                }
637            }
638        })
639    }
640
641    fn display_simple(&self) -> DisplayAbiTypeSimple<'_> {
642        DisplayAbiTypeSimple(self)
643    }
644}
645
646impl AsRef<AbiType> for AbiType {
647    #[inline]
648    fn as_ref(&self) -> &AbiType {
649        self
650    }
651}
652
653impl std::fmt::Display for AbiType {
654    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
655        let s = match self {
656            Self::Uint(n) => return write!(f, "uint{n}"),
657            Self::Int(n) => return write!(f, "int{n}"),
658            Self::VarUint(n) => return write!(f, "varuint{n}"),
659            Self::VarInt(n) => return write!(f, "varint{n}"),
660            Self::Bool => "bool",
661            Self::Cell => "cell",
662            Self::Address => "address",
663            Self::AddressStd => "address_std",
664            Self::Bytes => "bytes",
665            Self::FixedBytes(n) => return write!(f, "fixedbytes{n}"),
666            Self::String => "string",
667            Self::Token => "gram",
668            Self::Tuple(items) => {
669                if items.is_empty() {
670                    "()"
671                } else {
672                    let mut first = true;
673                    ok!(f.write_str("("));
674                    for item in items.as_ref() {
675                        if !std::mem::take(&mut first) {
676                            ok!(f.write_str(","));
677                        }
678                        ok!(std::fmt::Display::fmt(&item.ty, f));
679                    }
680                    ")"
681                }
682            }
683            Self::Array(ty) => return write!(f, "{ty}[]"),
684            Self::FixedArray(ty, n) => return write!(f, "{ty}[{n}]"),
685            Self::Map(key_ty, value_ty) => return write!(f, "map({key_ty},{value_ty})"),
686            Self::Optional(ty) => return write!(f, "optional({ty})"),
687            Self::Ref(ty) => return write!(f, "ref({ty})"),
688        };
689        f.write_str(s)
690    }
691}
692
693#[derive(Clone, Copy)]
694struct DisplayAbiTypeSimple<'a>(&'a AbiType);
695
696impl std::fmt::Display for DisplayAbiTypeSimple<'_> {
697    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
698        match self.0 {
699            AbiType::Tuple(_) => f.write_str("tuple"),
700            AbiType::Array(ty) => write!(f, "{}[]", ty.display_simple()),
701            AbiType::FixedArray(ty, n) => write!(f, "{}[{n}]", ty.display_simple()),
702            AbiType::Map(key_ty, value_ty) => {
703                write!(f, "map({key_ty},{})", value_ty.display_simple())
704            }
705            AbiType::Optional(ty) => write!(f, "optional({})", ty.display_simple()),
706            AbiType::Ref(ty) => write!(f, "ref({})", ty.display_simple()),
707            ty => std::fmt::Display::fmt(ty, f),
708        }
709    }
710}
711
712impl PartialEq for WithoutName<AbiType> {
713    fn eq(&self, other: &Self) -> bool {
714        match (&self.0, &other.0) {
715            (AbiType::Uint(a), AbiType::Uint(b)) => a.eq(b),
716            (AbiType::Int(a), AbiType::Int(b)) => a.eq(b),
717            (AbiType::VarUint(a), AbiType::VarUint(b)) => a.eq(b),
718            (AbiType::VarInt(a), AbiType::VarInt(b)) => a.eq(b),
719            (AbiType::Bool, AbiType::Bool) => true,
720            (AbiType::Cell, AbiType::Cell) => true,
721            (AbiType::Address, AbiType::Address) => true,
722            (AbiType::AddressStd, AbiType::AddressStd) => true,
723            (AbiType::Bytes, AbiType::Bytes) => true,
724            (AbiType::FixedBytes(a), AbiType::FixedBytes(b)) => a.eq(b),
725            (AbiType::String, AbiType::String) => true,
726            (AbiType::Token, AbiType::Token) => true,
727            (AbiType::Tuple(a), AbiType::Tuple(b)) => {
728                WithoutName::wrap_slice(a.as_ref()).eq(WithoutName::wrap_slice(b.as_ref()))
729            }
730            (AbiType::Array(a), AbiType::Array(b)) => {
731                WithoutName::wrap(a.as_ref()).eq(WithoutName::wrap(b.as_ref()))
732            }
733            (AbiType::FixedArray(a, an), AbiType::FixedArray(b, bn)) => {
734                WithoutName::wrap(a.as_ref()).eq(WithoutName::wrap(b.as_ref())) && an.eq(bn)
735            }
736            (AbiType::Map(ak, av), AbiType::Map(bk, bv)) => {
737                ak.eq(bk) && WithoutName::wrap(av.as_ref()).eq(WithoutName::wrap(bv.as_ref()))
738            }
739            (AbiType::Optional(a), AbiType::Optional(b)) => {
740                WithoutName::wrap(a.as_ref()).eq(WithoutName::wrap(b.as_ref()))
741            }
742            (AbiType::Ref(a), AbiType::Ref(b)) => {
743                WithoutName::wrap(a.as_ref()).eq(WithoutName::wrap(b.as_ref()))
744            }
745            _ => false,
746        }
747    }
748}
749
750impl Hash for WithoutName<AbiType> {
751    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
752        core::mem::discriminant(&self.0).hash(state);
753        match &self.0 {
754            AbiType::Uint(x) => x.hash(state),
755            AbiType::Int(x) => x.hash(state),
756            AbiType::VarUint(x) => x.hash(state),
757            AbiType::VarInt(x) => x.hash(state),
758            AbiType::Bool => {}
759            AbiType::Cell => {}
760            AbiType::Address => {}
761            AbiType::AddressStd => {}
762            AbiType::Bytes => {}
763            AbiType::FixedBytes(x) => x.hash(state),
764            AbiType::String => {}
765            AbiType::Token => {}
766            AbiType::Tuple(x) => WithoutName::wrap_slice(x.as_ref()).hash(state),
767            AbiType::Array(x) => WithoutName::wrap(x.as_ref()).hash(state),
768            AbiType::FixedArray(x, n) => {
769                WithoutName::wrap(x.as_ref()).hash(state);
770                n.hash(state);
771            }
772            AbiType::Map(k, v) => {
773                k.hash(state);
774                WithoutName::wrap(v.as_ref()).hash(state);
775            }
776            AbiType::Optional(x) => WithoutName::wrap(x.as_ref()).hash(state),
777            AbiType::Ref(x) => WithoutName::wrap(x.as_ref()).hash(state),
778        }
779    }
780}
781
782/// An iterator that flattens the first-level tuple.
783#[derive(Clone)]
784pub enum AbiTypeFlatten {
785    #[doc(hidden)]
786    Single(Option<AbiType>),
787    #[doc(hidden)]
788    Tuple(Vec<NamedAbiType>),
789}
790
791impl Iterator for AbiTypeFlatten {
792    type Item = AbiType;
793
794    fn size_hint(&self) -> (usize, Option<usize>) {
795        let size = match self {
796            Self::Single(item) => item.is_some() as usize,
797            Self::Tuple(items) => items.len(),
798        };
799        (size, Some(size))
800    }
801
802    fn next(&mut self) -> Option<Self::Item> {
803        match self {
804            Self::Single(item) => item.take(),
805            Self::Tuple(items) => items.pop().map(|item| item.ty),
806        }
807    }
808}
809
810/// ABI type which has a fixed bits representation
811/// and therefore can be used as a map key.
812#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
813pub enum PlainAbiType {
814    /// Unsigned integer of n bits.
815    Uint(u16),
816    /// Signed integer of n bits.
817    Int(u16),
818    /// Boolean.
819    Bool,
820    /// Internal address ([`IntAddr`]).
821    ///
822    /// [`IntAddr`]: crate::models::message::IntAddr
823    Address,
824}
825
826impl PlainAbiType {
827    /// Returns the maximum number of bits that this type can occupy.
828    pub fn key_bits(&self) -> u16 {
829        match self {
830            Self::Uint(n) | Self::Int(n) => *n,
831            Self::Bool => 1,
832            Self::Address => StdAddr::BITS_WITHOUT_ANYCAST,
833        }
834    }
835}
836
837impl From<PlainAbiType> for AbiType {
838    fn from(value: PlainAbiType) -> Self {
839        match value {
840            PlainAbiType::Uint(n) => Self::Uint(n),
841            PlainAbiType::Int(n) => Self::Int(n),
842            PlainAbiType::Bool => Self::Bool,
843            PlainAbiType::Address => Self::Address,
844        }
845    }
846}
847
848impl FromStr for PlainAbiType {
849    type Err = ParseAbiTypeError;
850
851    fn from_str(s: &str) -> Result<Self, Self::Err> {
852        Ok(match s {
853            "bool" => Self::Bool,
854            "address" => Self::Address,
855            s => {
856                if let Some(s) = s.strip_prefix("uint") {
857                    Self::Uint(ok!(s
858                        .parse::<u16>()
859                        .map_err(ParseAbiTypeError::InvalidBitLen)))
860                } else if let Some(s) = s.strip_prefix("int") {
861                    Self::Int(ok!(s
862                        .parse::<u16>()
863                        .map_err(ParseAbiTypeError::InvalidBitLen)))
864                } else {
865                    return Err(ParseAbiTypeError::UnknownType);
866                }
867            }
868        })
869    }
870}
871
872impl std::fmt::Display for PlainAbiType {
873    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
874        let s = match self {
875            Self::Uint(n) => return write!(f, "uint{n}"),
876            Self::Int(n) => return write!(f, "int{n}"),
877            Self::Bool => "bool",
878            Self::Address => "address",
879        };
880        f.write_str(s)
881    }
882}
883
884#[inline]
885fn collect_str<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
886where
887    T: std::fmt::Display,
888    S: serde::ser::Serializer,
889{
890    serializer.collect_str(value)
891}
892
893#[cfg(test)]
894mod tests {
895    use std::collections::BTreeMap;
896
897    use super::*;
898    use crate::abi::traits::{WithAbiType, WithPlainAbiType};
899
900    #[test]
901    fn correct_full_signature() {
902        macro_rules! assert_eq_sig {
903            ($expr:expr, $signature:literal) => {
904                assert_eq!(($expr).to_string(), $signature)
905            };
906        }
907
908        assert_eq_sig!(AbiType::Uint(100), "uint100");
909        assert_eq_sig!(AbiType::Int(100), "int100");
910        assert_eq_sig!(AbiType::varuint(16), "varuint16");
911        assert_eq_sig!(AbiType::varint(16), "varint16");
912        assert_eq_sig!(AbiType::Bool, "bool");
913        assert_eq_sig!(AbiType::Cell, "cell");
914        assert_eq_sig!(AbiType::Address, "address");
915        assert_eq_sig!(AbiType::Bytes, "bytes");
916        assert_eq_sig!(AbiType::FixedBytes(123), "fixedbytes123");
917        assert_eq_sig!(AbiType::String, "string");
918        assert_eq_sig!(AbiType::Token, "gram");
919
920        assert_eq_sig!(AbiType::unnamed_tuple([]), "()");
921        assert_eq_sig!(AbiType::unnamed_tuple([AbiType::Uint(321)]), "(uint321)");
922        assert_eq_sig!(
923            AbiType::unnamed_tuple([AbiType::Uint(123), AbiType::Address]),
924            "(uint123,address)"
925        );
926
927        assert_eq_sig!(AbiType::array(AbiType::Address), "address[]");
928        assert_eq_sig!(
929            AbiType::array(AbiType::array(AbiType::Address)),
930            "address[][]"
931        );
932        assert_eq_sig!(AbiType::array(AbiType::unnamed_tuple([])), "()[]");
933        assert_eq_sig!(
934            AbiType::array(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
935            "(address,bool)[]"
936        );
937
938        assert_eq_sig!(AbiType::fixedarray(AbiType::Address, 10), "address[10]");
939        assert_eq_sig!(
940            AbiType::fixedarray(AbiType::fixedarray(AbiType::Address, 123), 321),
941            "address[123][321]"
942        );
943        assert_eq_sig!(
944            AbiType::fixedarray(AbiType::unnamed_tuple([]), 100),
945            "()[100]"
946        );
947        assert_eq_sig!(
948            AbiType::fixedarray(
949                AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool]),
950                1000
951            ),
952            "(address,bool)[1000]"
953        );
954
955        assert_eq_sig!(
956            AbiType::map(PlainAbiType::Uint(123), AbiType::Address),
957            "map(uint123,address)"
958        );
959        assert_eq_sig!(
960            AbiType::map(PlainAbiType::Uint(123), AbiType::unnamed_tuple([])),
961            "map(uint123,())"
962        );
963        assert_eq_sig!(
964            AbiType::map(
965                PlainAbiType::Uint(123),
966                AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])
967            ),
968            "map(uint123,(address,bool))"
969        );
970        assert_eq_sig!(
971            AbiType::map(
972                PlainAbiType::Uint(123),
973                AbiType::fixedarray(AbiType::Address, 123)
974            ),
975            "map(uint123,address[123])"
976        );
977
978        assert_eq_sig!(AbiType::optional(AbiType::Address), "optional(address)");
979        assert_eq_sig!(
980            AbiType::optional(AbiType::unnamed_tuple([])),
981            "optional(())"
982        );
983        assert_eq_sig!(
984            AbiType::optional(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
985            "optional((address,bool))"
986        );
987        assert_eq_sig!(
988            AbiType::optional(AbiType::fixedarray(AbiType::Address, 123)),
989            "optional(address[123])"
990        );
991
992        assert_eq_sig!(AbiType::reference(AbiType::Address), "ref(address)");
993        assert_eq_sig!(AbiType::reference(AbiType::unnamed_tuple([])), "ref(())");
994        assert_eq_sig!(
995            AbiType::reference(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
996            "ref((address,bool))"
997        );
998        assert_eq_sig!(
999            AbiType::reference(AbiType::fixedarray(AbiType::Address, 123)),
1000            "ref(address[123])"
1001        );
1002
1003        assert_eq_sig!(
1004            AbiType::array(AbiType::unnamed_tuple([
1005                AbiType::Bool,
1006                AbiType::Uint(123),
1007                AbiType::array(AbiType::map(
1008                    PlainAbiType::Address,
1009                    AbiType::unnamed_tuple([AbiType::Uint(32), AbiType::String]),
1010                )),
1011            ])),
1012            "(bool,uint123,map(address,(uint32,string))[])[]"
1013        );
1014    }
1015
1016    #[test]
1017    fn correct_simple_signature() {
1018        macro_rules! assert_eq_sig {
1019            ($expr:expr, $signature:literal) => {
1020                assert_eq!(format!("{}", ($expr).display_simple()), $signature)
1021            };
1022        }
1023
1024        assert_eq_sig!(AbiType::Uint(100), "uint100");
1025        assert_eq_sig!(AbiType::Int(100), "int100");
1026        assert_eq_sig!(AbiType::varuint(16), "varuint16");
1027        assert_eq_sig!(AbiType::varint(16), "varint16");
1028        assert_eq_sig!(AbiType::Bool, "bool");
1029        assert_eq_sig!(AbiType::Cell, "cell");
1030        assert_eq_sig!(AbiType::Address, "address");
1031        assert_eq_sig!(AbiType::Bytes, "bytes");
1032        assert_eq_sig!(AbiType::FixedBytes(123), "fixedbytes123");
1033        assert_eq_sig!(AbiType::String, "string");
1034        assert_eq_sig!(AbiType::Token, "gram");
1035
1036        assert_eq_sig!(AbiType::unnamed_tuple([]), "tuple");
1037        assert_eq_sig!(AbiType::unnamed_tuple([AbiType::Uint(321)]), "tuple");
1038        assert_eq_sig!(
1039            AbiType::unnamed_tuple([AbiType::Uint(123), AbiType::Address]),
1040            "tuple"
1041        );
1042
1043        assert_eq_sig!(AbiType::array(AbiType::Address), "address[]");
1044        assert_eq_sig!(
1045            AbiType::array(AbiType::array(AbiType::Address)),
1046            "address[][]"
1047        );
1048        assert_eq_sig!(AbiType::array(AbiType::unnamed_tuple([])), "tuple[]");
1049        assert_eq_sig!(
1050            AbiType::array(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
1051            "tuple[]"
1052        );
1053
1054        assert_eq_sig!(AbiType::fixedarray(AbiType::Address, 10), "address[10]");
1055        assert_eq_sig!(
1056            AbiType::fixedarray(AbiType::fixedarray(AbiType::Address, 123), 321),
1057            "address[123][321]"
1058        );
1059        assert_eq_sig!(
1060            AbiType::fixedarray(AbiType::unnamed_tuple([]), 100),
1061            "tuple[100]"
1062        );
1063        assert_eq_sig!(
1064            AbiType::fixedarray(
1065                AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool]),
1066                1000
1067            ),
1068            "tuple[1000]"
1069        );
1070
1071        assert_eq_sig!(
1072            AbiType::map(PlainAbiType::Uint(123), AbiType::Address),
1073            "map(uint123,address)"
1074        );
1075        assert_eq_sig!(
1076            AbiType::map(PlainAbiType::Uint(123), AbiType::unnamed_tuple([])),
1077            "map(uint123,tuple)"
1078        );
1079        assert_eq_sig!(
1080            AbiType::map(
1081                PlainAbiType::Uint(123),
1082                AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])
1083            ),
1084            "map(uint123,tuple)"
1085        );
1086        assert_eq_sig!(
1087            AbiType::map(
1088                PlainAbiType::Uint(123),
1089                AbiType::fixedarray(AbiType::Address, 123)
1090            ),
1091            "map(uint123,address[123])"
1092        );
1093
1094        assert_eq_sig!(AbiType::optional(AbiType::Address), "optional(address)");
1095        assert_eq_sig!(
1096            AbiType::optional(AbiType::unnamed_tuple([])),
1097            "optional(tuple)"
1098        );
1099        assert_eq_sig!(
1100            AbiType::optional(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
1101            "optional(tuple)"
1102        );
1103        assert_eq_sig!(
1104            AbiType::optional(AbiType::fixedarray(AbiType::Address, 123)),
1105            "optional(address[123])"
1106        );
1107
1108        assert_eq_sig!(AbiType::reference(AbiType::Address), "ref(address)");
1109        assert_eq_sig!(AbiType::reference(AbiType::unnamed_tuple([])), "ref(tuple)");
1110        assert_eq_sig!(
1111            AbiType::reference(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
1112            "ref(tuple)"
1113        );
1114        assert_eq_sig!(
1115            AbiType::reference(AbiType::fixedarray(AbiType::Address, 123)),
1116            "ref(address[123])"
1117        );
1118
1119        assert_eq_sig!(
1120            AbiType::array(AbiType::unnamed_tuple([
1121                AbiType::Bool,
1122                AbiType::Uint(123),
1123                AbiType::array(AbiType::map(
1124                    PlainAbiType::Address,
1125                    AbiType::unnamed_tuple([AbiType::Uint(32), AbiType::String]),
1126                )),
1127            ])),
1128            "tuple[]"
1129        );
1130    }
1131
1132    #[test]
1133    fn from_to_json() {
1134        const RAW: &str = r#"{
1135            "name":"info",
1136            "type":"tuple",
1137            "components": [
1138                {"name":"total","type":"uint64"},
1139                {"name":"withdrawValue","type":"uint64"},
1140                {"name":"reinvest","type":"bool"},
1141                {"name":"reward","type":"uint64"},
1142                {"name":"stakes","type":"map(uint64,uint64)"},
1143                {"components":[{"name":"remainingAmount","type":"uint64"},{"name":"lastWithdrawalTime","type":"uint64"},{"name":"withdrawalPeriod","type":"uint32"},{"name":"withdrawalValue","type":"uint64"},{"name":"owner","type":"address"}],"name":"vestings","type":"map(uint64,tuple)"},
1144                {"components":[{"name":"remainingAmount","type":"uint64"},{"name":"lastWithdrawalTime","type":"uint64"},{"name":"withdrawalPeriod","type":"uint32"},{"name":"withdrawalValue","type":"uint64"},{"name":"owner","type":"address"}],"name":"locks","type":"map(uint64,tuple)"},
1145                {"name":"vestingDonor","type":"address"},
1146                {"name":"lockDonor","type":"address"}
1147            ]
1148        }"#;
1149
1150        let ty = serde_json::from_str::<NamedAbiType>(RAW).unwrap();
1151
1152        let complex_item_ty = AbiType::tuple([
1153            ("remainingAmount", u64::abi_type()),
1154            ("lastWithdrawalTime", u64::abi_type()),
1155            ("withdrawalPeriod", u32::abi_type()),
1156            ("withdrawalValue", u64::abi_type()),
1157            ("owner", IntAddr::abi_type()),
1158        ]);
1159
1160        assert_eq!(
1161            ty,
1162            NamedAbiType::new(
1163                "info",
1164                AbiType::Tuple(Arc::from(vec![
1165                    NamedAbiType::new("total", u64::abi_type()),
1166                    NamedAbiType::new("withdrawValue", u64::abi_type()),
1167                    NamedAbiType::new("reinvest", bool::abi_type()),
1168                    NamedAbiType::new("reward", u64::abi_type()),
1169                    NamedAbiType::new("stakes", BTreeMap::<u64, u64>::abi_type()),
1170                    NamedAbiType::new(
1171                        "vestings",
1172                        AbiType::map(u64::plain_abi_type(), complex_item_ty.clone())
1173                    ),
1174                    NamedAbiType::new(
1175                        "locks",
1176                        AbiType::map(u64::plain_abi_type(), complex_item_ty)
1177                    ),
1178                    NamedAbiType::new("vestingDonor", IntAddr::abi_type()),
1179                    NamedAbiType::new("lockDonor", IntAddr::abi_type()),
1180                ]))
1181            )
1182        );
1183
1184        let normalized = serde_json::from_str::<serde_json::Value>(RAW).unwrap();
1185        let serialized = serde_json::to_value(ty).unwrap();
1186        assert_eq!(serialized, normalized);
1187    }
1188}