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::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    /// Byte array.
310    Bytes,
311    /// Byte array of fixed length.
312    FixedBytes(usize),
313    /// Utf8-encoded string.
314    String,
315    /// Variable length 120-bit integer ([`Tokens`]).
316    ///
317    /// [`Tokens`]: crate::num::Tokens
318    Token,
319    /// Product type.
320    Tuple(Arc<[NamedAbiType]>),
321    /// Array of elements of the specified ABI type.
322    Array(Arc<Self>),
323    /// Fixed-length array of elements of the specified ABI type.
324    FixedArray(Arc<Self>, usize),
325    /// Dictionary with the specified key and value ABI types.
326    Map(PlainAbiType, Arc<Self>),
327    /// Optional type.
328    Optional(Arc<Self>),
329    /// Type stored in a new cell.
330    Ref(Arc<Self>),
331}
332
333impl AbiType {
334    /// Returns a named ABI type.
335    pub fn named<T: Into<String>>(self, name: T) -> NamedAbiType {
336        NamedAbiType {
337            name: Arc::from(name.into()),
338            ty: self,
339        }
340    }
341
342    /// Tries to convert a generic ABI type into a plain ABI type.
343    pub fn as_plain(&self) -> Option<PlainAbiType> {
344        Some(match self {
345            Self::Uint(n) => PlainAbiType::Uint(*n),
346            Self::Int(n) => PlainAbiType::Int(*n),
347            Self::Bool => PlainAbiType::Bool,
348            Self::Address => PlainAbiType::Address,
349            _ => return None,
350        })
351    }
352
353    /// Returns the maximum number of bits and refs that this type can occupy.
354    pub fn max_size(&self) -> CellTreeStats {
355        match self {
356            Self::Uint(n) | Self::Int(n) => CellTreeStats {
357                bit_count: *n as _,
358                cell_count: 0,
359            },
360            Self::VarUint(n) | Self::VarInt(n) => {
361                let value_bytes: u8 = n.get() - 1;
362                let bit_count = (8 - value_bytes.leading_zeros()) as u64 + (value_bytes as u64 * 8);
363                CellTreeStats {
364                    bit_count,
365                    cell_count: 0,
366                }
367            }
368            Self::Bool => CellTreeStats {
369                bit_count: 1,
370                cell_count: 0,
371            },
372            Self::Cell | Self::Bytes | Self::FixedBytes(_) | Self::String | Self::Ref(_) => {
373                CellTreeStats {
374                    bit_count: 0,
375                    cell_count: 1,
376                }
377            }
378            Self::Address => CellTreeStats {
379                bit_count: IntAddr::BITS_MAX as _,
380                cell_count: 0,
381            },
382            Self::Token => CellTreeStats {
383                bit_count: Tokens::MAX_BITS as _,
384                cell_count: 0,
385            },
386            Self::Array(_) => CellTreeStats {
387                bit_count: 33,
388                cell_count: 1,
389            },
390            Self::FixedArray(..) | Self::Map(..) => CellTreeStats {
391                bit_count: 1,
392                cell_count: 1,
393            },
394            Self::Optional(ty) => {
395                let ty_size = ty.max_size();
396                if ty_size.bit_count < MAX_BIT_LEN as u64
397                    && ty_size.cell_count < MAX_REF_COUNT as u64
398                {
399                    CellTreeStats {
400                        bit_count: 1,
401                        cell_count: 0,
402                    } + ty_size
403                } else {
404                    CellTreeStats {
405                        bit_count: 1,
406                        cell_count: 1,
407                    }
408                }
409            }
410            Self::Tuple(items) => items.iter().map(|item| item.ty.max_size()).sum(),
411        }
412    }
413
414    /// Returns the maximum number of bits that this type can occupy.
415    pub fn max_bits(&self) -> usize {
416        self.max_size().bit_count as usize
417    }
418
419    /// Returns the maximum number of cells that this type can occupy.
420    pub fn max_refs(&self) -> usize {
421        self.max_size().cell_count as usize
422    }
423
424    fn components(&self) -> Option<&[NamedAbiType]> {
425        match self {
426            Self::Tuple(types) => Some(types),
427            Self::Array(ty) => ty.components(),
428            Self::FixedArray(ty, _) => ty.components(),
429            Self::Map(_, value_ty) => value_ty.components(),
430            Self::Optional(ty) => ty.components(),
431            Self::Ref(ty) => ty.components(),
432            _ => None,
433        }
434    }
435
436    fn components_mut(&mut self) -> Option<&mut Arc<[NamedAbiType]>> {
437        match self {
438            Self::Tuple(types) => Some(types),
439            Self::Array(ty) => Arc::make_mut(ty).components_mut(),
440            Self::FixedArray(ty, _) => Arc::make_mut(ty).components_mut(),
441            Self::Map(_, value_ty) => Arc::make_mut(value_ty).components_mut(),
442            Self::Optional(ty) => Arc::make_mut(ty).components_mut(),
443            Self::Ref(ty) => Arc::make_mut(ty).components_mut(),
444            _ => None,
445        }
446    }
447
448    /// Returns an iterator with the first-level tuple flattened.
449    ///
450    /// Can be used to pass an ABI struct as arguments to the
451    /// [`FunctionBuilder::with_unnamed_inputs`] or [`FunctionBuilder::with_unnamed_outputs`]
452    ///
453    /// [`FunctionBuilder::with_unnamed_inputs`]: fn@crate::abi::FunctionBuilder::with_unnamed_inputs
454    /// [`FunctionBuilder::with_unnamed_outputs`]: fn@crate::abi::FunctionBuilder::with_unnamed_outputs
455    pub fn flatten(self) -> AbiTypeFlatten {
456        match self {
457            AbiType::Tuple(tuple) => {
458                let mut items = tuple.to_vec();
459                items.reverse();
460                AbiTypeFlatten::Tuple(items)
461            }
462            ty => AbiTypeFlatten::Single(Some(ty)),
463        }
464    }
465
466    /// Simple `varuintN` type constructor.
467    #[inline]
468    pub fn varuint(size: u8) -> Self {
469        Self::VarUint(NonZeroU8::new(size).unwrap())
470    }
471
472    /// Simple `varintN` type constructor.
473    #[inline]
474    pub fn varint(size: u8) -> Self {
475        Self::VarInt(NonZeroU8::new(size).unwrap())
476    }
477
478    /// Simple `tuple` type constructor.
479    #[inline]
480    pub fn tuple<I, T>(values: I) -> Self
481    where
482        I: IntoIterator<Item = T>,
483        NamedAbiType: From<T>,
484    {
485        Self::Tuple(values.into_iter().map(NamedAbiType::from).collect())
486    }
487
488    /// Simple `tuple` type constructor.
489    #[inline]
490    pub fn unnamed_tuple<I>(values: I) -> Self
491    where
492        I: IntoIterator<Item = AbiType>,
493    {
494        Self::Tuple(
495            values
496                .into_iter()
497                .enumerate()
498                .map(|(i, ty)| NamedAbiType::from_index(i, ty))
499                .collect(),
500        )
501    }
502
503    /// Simple `array` type constructor.
504    #[inline]
505    pub fn array<T>(ty: T) -> Self
506    where
507        Arc<AbiType>: From<T>,
508    {
509        Self::Array(Arc::<AbiType>::from(ty))
510    }
511
512    /// Simple `fixedarrayN` type constructor.
513    #[inline]
514    pub fn fixedarray<T>(ty: T, len: usize) -> Self
515    where
516        Arc<AbiType>: From<T>,
517    {
518        Self::FixedArray(Arc::<AbiType>::from(ty), len)
519    }
520
521    /// Simple `tuple` type constructor.
522    #[inline]
523    pub fn map<V>(key_ty: PlainAbiType, value_ty: V) -> Self
524    where
525        Arc<AbiType>: From<V>,
526    {
527        Self::Map(key_ty, Arc::<AbiType>::from(value_ty))
528    }
529
530    /// Simple `optional` type constructor.
531    #[inline]
532    pub fn optional<T>(ty: T) -> Self
533    where
534        Arc<AbiType>: From<T>,
535    {
536        Self::Optional(Arc::<AbiType>::from(ty))
537    }
538
539    /// Simple `ref` type constructor.
540    #[inline]
541    pub fn reference<T>(ty: T) -> Self
542    where
543        Arc<AbiType>: From<T>,
544    {
545        Self::Ref(Arc::<AbiType>::from(ty))
546    }
547
548    fn from_simple_str(s: &str) -> Result<Self, ParseAbiTypeError> {
549        if let Some(arr_ty) = s.strip_suffix(']') {
550            let (ty, len) = ok!(arr_ty
551                .rsplit_once('[')
552                .ok_or(ParseAbiTypeError::InvalidArrayType));
553
554            let len = if len.is_empty() {
555                None
556            } else {
557                Some(ok!(len
558                    .parse::<usize>()
559                    .map_err(ParseAbiTypeError::InvalidArrayLength)))
560            };
561
562            let ty = ok!(Self::from_simple_str(ty).map(Arc::new));
563            return Ok(match len {
564                None => Self::Array(ty),
565                Some(len) => Self::FixedArray(ty, len),
566            });
567        }
568
569        Ok(match s {
570            "bool" => Self::Bool,
571            "cell" => Self::Cell,
572            "address" => Self::Address,
573            "bytes" => Self::Bytes,
574            "string" => Self::String,
575            "gram" | "token" => Self::Token,
576            "tuple" => Self::Tuple(Arc::from([].as_slice())),
577            _ => {
578                if let Some(s) = s.strip_prefix("uint") {
579                    Self::Uint(ok!(s
580                        .parse::<u16>()
581                        .map_err(ParseAbiTypeError::InvalidBitLen)))
582                } else if let Some(s) = s.strip_prefix("int") {
583                    Self::Int(ok!(s
584                        .parse::<u16>()
585                        .map_err(ParseAbiTypeError::InvalidBitLen)))
586                } else if let Some(s) = s.strip_prefix("varuint") {
587                    Self::VarUint(ok!(s
588                        .parse::<NonZeroU8>()
589                        .map_err(ParseAbiTypeError::InvalidByteLen)))
590                } else if let Some(s) = s.strip_prefix("varint") {
591                    Self::VarInt(ok!(s
592                        .parse::<NonZeroU8>()
593                        .map_err(ParseAbiTypeError::InvalidByteLen)))
594                } else if let Some(s) = s.strip_prefix("fixedbytes") {
595                    Self::FixedBytes(ok!(s
596                        .parse::<usize>()
597                        .map_err(ParseAbiTypeError::InvalidByteLen)))
598                } else if let Some(s) = s.strip_prefix("map(") {
599                    let s = ok!(s
600                        .strip_suffix(')')
601                        .ok_or(ParseAbiTypeError::UnterminatedInnerType));
602                    let (key_ty, value_ty) = ok!(s
603                        .split_once(',')
604                        .ok_or(ParseAbiTypeError::ValueTypeNotFound));
605
606                    Self::Map(
607                        ok!(PlainAbiType::from_str(key_ty)),
608                        ok!(Self::from_simple_str(value_ty).map(Arc::new)),
609                    )
610                } else if let Some(s) = s.strip_prefix("optional(") {
611                    let s = ok!(s
612                        .strip_suffix(')')
613                        .ok_or(ParseAbiTypeError::UnterminatedInnerType));
614
615                    Self::Optional(ok!(Self::from_simple_str(s).map(Arc::new)))
616                } else if let Some(s) = s.strip_prefix("ref(") {
617                    let s = ok!(s
618                        .strip_suffix(')')
619                        .ok_or(ParseAbiTypeError::UnterminatedInnerType));
620
621                    Self::Ref(ok!(Self::from_simple_str(s).map(Arc::new)))
622                } else {
623                    return Err(ParseAbiTypeError::UnknownType);
624                }
625            }
626        })
627    }
628
629    fn display_simple(&self) -> DisplayAbiTypeSimple<'_> {
630        DisplayAbiTypeSimple(self)
631    }
632}
633
634impl AsRef<AbiType> for AbiType {
635    #[inline]
636    fn as_ref(&self) -> &AbiType {
637        self
638    }
639}
640
641impl std::fmt::Display for AbiType {
642    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
643        let s = match self {
644            Self::Uint(n) => return write!(f, "uint{n}"),
645            Self::Int(n) => return write!(f, "int{n}"),
646            Self::VarUint(n) => return write!(f, "varuint{n}"),
647            Self::VarInt(n) => return write!(f, "varint{n}"),
648            Self::Bool => "bool",
649            Self::Cell => "cell",
650            Self::Address => "address",
651            Self::Bytes => "bytes",
652            Self::FixedBytes(n) => return write!(f, "fixedbytes{n}"),
653            Self::String => "string",
654            Self::Token => "gram",
655            Self::Tuple(items) => {
656                if items.is_empty() {
657                    "()"
658                } else {
659                    let mut first = true;
660                    ok!(f.write_str("("));
661                    for item in items.as_ref() {
662                        if !std::mem::take(&mut first) {
663                            ok!(f.write_str(","));
664                        }
665                        ok!(std::fmt::Display::fmt(&item.ty, f));
666                    }
667                    ")"
668                }
669            }
670            Self::Array(ty) => return write!(f, "{ty}[]"),
671            Self::FixedArray(ty, n) => return write!(f, "{ty}[{n}]"),
672            Self::Map(key_ty, value_ty) => return write!(f, "map({key_ty},{value_ty})"),
673            Self::Optional(ty) => return write!(f, "optional({ty})"),
674            Self::Ref(ty) => return write!(f, "ref({ty})"),
675        };
676        f.write_str(s)
677    }
678}
679
680#[derive(Clone, Copy)]
681struct DisplayAbiTypeSimple<'a>(&'a AbiType);
682
683impl std::fmt::Display for DisplayAbiTypeSimple<'_> {
684    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
685        match self.0 {
686            AbiType::Tuple(_) => f.write_str("tuple"),
687            AbiType::Array(ty) => write!(f, "{}[]", ty.display_simple()),
688            AbiType::FixedArray(ty, n) => write!(f, "{}[{n}]", ty.display_simple()),
689            AbiType::Map(key_ty, value_ty) => {
690                write!(f, "map({key_ty},{})", value_ty.display_simple())
691            }
692            AbiType::Optional(ty) => write!(f, "optional({})", ty.display_simple()),
693            AbiType::Ref(ty) => write!(f, "ref({})", ty.display_simple()),
694            ty => std::fmt::Display::fmt(ty, f),
695        }
696    }
697}
698
699impl PartialEq for WithoutName<AbiType> {
700    fn eq(&self, other: &Self) -> bool {
701        match (&self.0, &other.0) {
702            (AbiType::Uint(a), AbiType::Uint(b)) => a.eq(b),
703            (AbiType::Int(a), AbiType::Int(b)) => a.eq(b),
704            (AbiType::VarUint(a), AbiType::VarUint(b)) => a.eq(b),
705            (AbiType::VarInt(a), AbiType::VarInt(b)) => a.eq(b),
706            (AbiType::Bool, AbiType::Bool) => true,
707            (AbiType::Cell, AbiType::Cell) => true,
708            (AbiType::Address, AbiType::Address) => true,
709            (AbiType::Bytes, AbiType::Bytes) => true,
710            (AbiType::FixedBytes(a), AbiType::FixedBytes(b)) => a.eq(b),
711            (AbiType::String, AbiType::String) => true,
712            (AbiType::Token, AbiType::Token) => true,
713            (AbiType::Tuple(a), AbiType::Tuple(b)) => {
714                WithoutName::wrap_slice(a.as_ref()).eq(WithoutName::wrap_slice(b.as_ref()))
715            }
716            (AbiType::Array(a), AbiType::Array(b)) => {
717                WithoutName::wrap(a.as_ref()).eq(WithoutName::wrap(b.as_ref()))
718            }
719            (AbiType::FixedArray(a, an), AbiType::FixedArray(b, bn)) => {
720                WithoutName::wrap(a.as_ref()).eq(WithoutName::wrap(b.as_ref())) && an.eq(bn)
721            }
722            (AbiType::Map(ak, av), AbiType::Map(bk, bv)) => {
723                ak.eq(bk) && WithoutName::wrap(av.as_ref()).eq(WithoutName::wrap(bv.as_ref()))
724            }
725            (AbiType::Optional(a), AbiType::Optional(b)) => {
726                WithoutName::wrap(a.as_ref()).eq(WithoutName::wrap(b.as_ref()))
727            }
728            (AbiType::Ref(a), AbiType::Ref(b)) => {
729                WithoutName::wrap(a.as_ref()).eq(WithoutName::wrap(b.as_ref()))
730            }
731            _ => false,
732        }
733    }
734}
735
736impl Hash for WithoutName<AbiType> {
737    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
738        core::mem::discriminant(&self.0).hash(state);
739        match &self.0 {
740            AbiType::Uint(x) => x.hash(state),
741            AbiType::Int(x) => x.hash(state),
742            AbiType::VarUint(x) => x.hash(state),
743            AbiType::VarInt(x) => x.hash(state),
744            AbiType::Bool => {}
745            AbiType::Cell => {}
746            AbiType::Address => {}
747            AbiType::Bytes => {}
748            AbiType::FixedBytes(x) => x.hash(state),
749            AbiType::String => {}
750            AbiType::Token => {}
751            AbiType::Tuple(x) => WithoutName::wrap_slice(x.as_ref()).hash(state),
752            AbiType::Array(x) => WithoutName::wrap(x.as_ref()).hash(state),
753            AbiType::FixedArray(x, n) => {
754                WithoutName::wrap(x.as_ref()).hash(state);
755                n.hash(state);
756            }
757            AbiType::Map(k, v) => {
758                k.hash(state);
759                WithoutName::wrap(v.as_ref()).hash(state);
760            }
761            AbiType::Optional(x) => WithoutName::wrap(x.as_ref()).hash(state),
762            AbiType::Ref(x) => WithoutName::wrap(x.as_ref()).hash(state),
763        }
764    }
765}
766
767/// An iterator that flattens the first-level tuple.
768#[derive(Clone)]
769pub enum AbiTypeFlatten {
770    #[doc(hidden)]
771    Single(Option<AbiType>),
772    #[doc(hidden)]
773    Tuple(Vec<NamedAbiType>),
774}
775
776impl Iterator for AbiTypeFlatten {
777    type Item = AbiType;
778
779    fn size_hint(&self) -> (usize, Option<usize>) {
780        let size = match self {
781            Self::Single(item) => item.is_some() as usize,
782            Self::Tuple(items) => items.len(),
783        };
784        (size, Some(size))
785    }
786
787    fn next(&mut self) -> Option<Self::Item> {
788        match self {
789            Self::Single(item) => item.take(),
790            Self::Tuple(items) => items.pop().map(|item| item.ty),
791        }
792    }
793}
794
795/// ABI type which has a fixed bits representation
796/// and therefore can be used as a map key.
797#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
798pub enum PlainAbiType {
799    /// Unsigned integer of n bits.
800    Uint(u16),
801    /// Signed integer of n bits.
802    Int(u16),
803    /// Boolean.
804    Bool,
805    /// Internal address ([`IntAddr`]).
806    ///
807    /// [`IntAddr`]: crate::models::message::IntAddr
808    Address,
809}
810
811impl PlainAbiType {
812    /// Returns the maximum number of bits that this type can occupy.
813    pub fn key_bits(&self) -> u16 {
814        match self {
815            Self::Uint(n) | Self::Int(n) => *n,
816            Self::Bool => 1,
817            Self::Address => StdAddr::BITS_WITHOUT_ANYCAST,
818        }
819    }
820}
821
822impl From<PlainAbiType> for AbiType {
823    fn from(value: PlainAbiType) -> Self {
824        match value {
825            PlainAbiType::Uint(n) => Self::Uint(n),
826            PlainAbiType::Int(n) => Self::Int(n),
827            PlainAbiType::Bool => Self::Bool,
828            PlainAbiType::Address => Self::Address,
829        }
830    }
831}
832
833impl FromStr for PlainAbiType {
834    type Err = ParseAbiTypeError;
835
836    fn from_str(s: &str) -> Result<Self, Self::Err> {
837        Ok(match s {
838            "bool" => Self::Bool,
839            "address" => Self::Address,
840            s => {
841                if let Some(s) = s.strip_prefix("uint") {
842                    Self::Uint(ok!(s
843                        .parse::<u16>()
844                        .map_err(ParseAbiTypeError::InvalidBitLen)))
845                } else if let Some(s) = s.strip_prefix("int") {
846                    Self::Int(ok!(s
847                        .parse::<u16>()
848                        .map_err(ParseAbiTypeError::InvalidBitLen)))
849                } else {
850                    return Err(ParseAbiTypeError::UnknownType);
851                }
852            }
853        })
854    }
855}
856
857impl std::fmt::Display for PlainAbiType {
858    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
859        let s = match self {
860            Self::Uint(n) => return write!(f, "uint{n}"),
861            Self::Int(n) => return write!(f, "int{n}"),
862            Self::Bool => "bool",
863            Self::Address => "address",
864        };
865        f.write_str(s)
866    }
867}
868
869#[inline]
870fn collect_str<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
871where
872    T: std::fmt::Display,
873    S: serde::ser::Serializer,
874{
875    serializer.collect_str(value)
876}
877
878#[cfg(test)]
879mod tests {
880    use std::collections::BTreeMap;
881
882    use super::*;
883    use crate::abi::traits::{WithAbiType, WithPlainAbiType};
884
885    #[test]
886    fn correct_full_signature() {
887        macro_rules! assert_eq_sig {
888            ($expr:expr, $signature:literal) => {
889                assert_eq!(($expr).to_string(), $signature)
890            };
891        }
892
893        assert_eq_sig!(AbiType::Uint(100), "uint100");
894        assert_eq_sig!(AbiType::Int(100), "int100");
895        assert_eq_sig!(AbiType::varuint(16), "varuint16");
896        assert_eq_sig!(AbiType::varint(16), "varint16");
897        assert_eq_sig!(AbiType::Bool, "bool");
898        assert_eq_sig!(AbiType::Cell, "cell");
899        assert_eq_sig!(AbiType::Address, "address");
900        assert_eq_sig!(AbiType::Bytes, "bytes");
901        assert_eq_sig!(AbiType::FixedBytes(123), "fixedbytes123");
902        assert_eq_sig!(AbiType::String, "string");
903        assert_eq_sig!(AbiType::Token, "gram");
904
905        assert_eq_sig!(AbiType::unnamed_tuple([]), "()");
906        assert_eq_sig!(AbiType::unnamed_tuple([AbiType::Uint(321)]), "(uint321)");
907        assert_eq_sig!(
908            AbiType::unnamed_tuple([AbiType::Uint(123), AbiType::Address]),
909            "(uint123,address)"
910        );
911
912        assert_eq_sig!(AbiType::array(AbiType::Address), "address[]");
913        assert_eq_sig!(
914            AbiType::array(AbiType::array(AbiType::Address)),
915            "address[][]"
916        );
917        assert_eq_sig!(AbiType::array(AbiType::unnamed_tuple([])), "()[]");
918        assert_eq_sig!(
919            AbiType::array(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
920            "(address,bool)[]"
921        );
922
923        assert_eq_sig!(AbiType::fixedarray(AbiType::Address, 10), "address[10]");
924        assert_eq_sig!(
925            AbiType::fixedarray(AbiType::fixedarray(AbiType::Address, 123), 321),
926            "address[123][321]"
927        );
928        assert_eq_sig!(
929            AbiType::fixedarray(AbiType::unnamed_tuple([]), 100),
930            "()[100]"
931        );
932        assert_eq_sig!(
933            AbiType::fixedarray(
934                AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool]),
935                1000
936            ),
937            "(address,bool)[1000]"
938        );
939
940        assert_eq_sig!(
941            AbiType::map(PlainAbiType::Uint(123), AbiType::Address),
942            "map(uint123,address)"
943        );
944        assert_eq_sig!(
945            AbiType::map(PlainAbiType::Uint(123), AbiType::unnamed_tuple([])),
946            "map(uint123,())"
947        );
948        assert_eq_sig!(
949            AbiType::map(
950                PlainAbiType::Uint(123),
951                AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])
952            ),
953            "map(uint123,(address,bool))"
954        );
955        assert_eq_sig!(
956            AbiType::map(
957                PlainAbiType::Uint(123),
958                AbiType::fixedarray(AbiType::Address, 123)
959            ),
960            "map(uint123,address[123])"
961        );
962
963        assert_eq_sig!(AbiType::optional(AbiType::Address), "optional(address)");
964        assert_eq_sig!(
965            AbiType::optional(AbiType::unnamed_tuple([])),
966            "optional(())"
967        );
968        assert_eq_sig!(
969            AbiType::optional(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
970            "optional((address,bool))"
971        );
972        assert_eq_sig!(
973            AbiType::optional(AbiType::fixedarray(AbiType::Address, 123)),
974            "optional(address[123])"
975        );
976
977        assert_eq_sig!(AbiType::reference(AbiType::Address), "ref(address)");
978        assert_eq_sig!(AbiType::reference(AbiType::unnamed_tuple([])), "ref(())");
979        assert_eq_sig!(
980            AbiType::reference(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
981            "ref((address,bool))"
982        );
983        assert_eq_sig!(
984            AbiType::reference(AbiType::fixedarray(AbiType::Address, 123)),
985            "ref(address[123])"
986        );
987
988        assert_eq_sig!(
989            AbiType::array(AbiType::unnamed_tuple([
990                AbiType::Bool,
991                AbiType::Uint(123),
992                AbiType::array(AbiType::map(
993                    PlainAbiType::Address,
994                    AbiType::unnamed_tuple([AbiType::Uint(32), AbiType::String]),
995                )),
996            ])),
997            "(bool,uint123,map(address,(uint32,string))[])[]"
998        );
999    }
1000
1001    #[test]
1002    fn correct_simple_signature() {
1003        macro_rules! assert_eq_sig {
1004            ($expr:expr, $signature:literal) => {
1005                assert_eq!(format!("{}", ($expr).display_simple()), $signature)
1006            };
1007        }
1008
1009        assert_eq_sig!(AbiType::Uint(100), "uint100");
1010        assert_eq_sig!(AbiType::Int(100), "int100");
1011        assert_eq_sig!(AbiType::varuint(16), "varuint16");
1012        assert_eq_sig!(AbiType::varint(16), "varint16");
1013        assert_eq_sig!(AbiType::Bool, "bool");
1014        assert_eq_sig!(AbiType::Cell, "cell");
1015        assert_eq_sig!(AbiType::Address, "address");
1016        assert_eq_sig!(AbiType::Bytes, "bytes");
1017        assert_eq_sig!(AbiType::FixedBytes(123), "fixedbytes123");
1018        assert_eq_sig!(AbiType::String, "string");
1019        assert_eq_sig!(AbiType::Token, "gram");
1020
1021        assert_eq_sig!(AbiType::unnamed_tuple([]), "tuple");
1022        assert_eq_sig!(AbiType::unnamed_tuple([AbiType::Uint(321)]), "tuple");
1023        assert_eq_sig!(
1024            AbiType::unnamed_tuple([AbiType::Uint(123), AbiType::Address]),
1025            "tuple"
1026        );
1027
1028        assert_eq_sig!(AbiType::array(AbiType::Address), "address[]");
1029        assert_eq_sig!(
1030            AbiType::array(AbiType::array(AbiType::Address)),
1031            "address[][]"
1032        );
1033        assert_eq_sig!(AbiType::array(AbiType::unnamed_tuple([])), "tuple[]");
1034        assert_eq_sig!(
1035            AbiType::array(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
1036            "tuple[]"
1037        );
1038
1039        assert_eq_sig!(AbiType::fixedarray(AbiType::Address, 10), "address[10]");
1040        assert_eq_sig!(
1041            AbiType::fixedarray(AbiType::fixedarray(AbiType::Address, 123), 321),
1042            "address[123][321]"
1043        );
1044        assert_eq_sig!(
1045            AbiType::fixedarray(AbiType::unnamed_tuple([]), 100),
1046            "tuple[100]"
1047        );
1048        assert_eq_sig!(
1049            AbiType::fixedarray(
1050                AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool]),
1051                1000
1052            ),
1053            "tuple[1000]"
1054        );
1055
1056        assert_eq_sig!(
1057            AbiType::map(PlainAbiType::Uint(123), AbiType::Address),
1058            "map(uint123,address)"
1059        );
1060        assert_eq_sig!(
1061            AbiType::map(PlainAbiType::Uint(123), AbiType::unnamed_tuple([])),
1062            "map(uint123,tuple)"
1063        );
1064        assert_eq_sig!(
1065            AbiType::map(
1066                PlainAbiType::Uint(123),
1067                AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])
1068            ),
1069            "map(uint123,tuple)"
1070        );
1071        assert_eq_sig!(
1072            AbiType::map(
1073                PlainAbiType::Uint(123),
1074                AbiType::fixedarray(AbiType::Address, 123)
1075            ),
1076            "map(uint123,address[123])"
1077        );
1078
1079        assert_eq_sig!(AbiType::optional(AbiType::Address), "optional(address)");
1080        assert_eq_sig!(
1081            AbiType::optional(AbiType::unnamed_tuple([])),
1082            "optional(tuple)"
1083        );
1084        assert_eq_sig!(
1085            AbiType::optional(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
1086            "optional(tuple)"
1087        );
1088        assert_eq_sig!(
1089            AbiType::optional(AbiType::fixedarray(AbiType::Address, 123)),
1090            "optional(address[123])"
1091        );
1092
1093        assert_eq_sig!(AbiType::reference(AbiType::Address), "ref(address)");
1094        assert_eq_sig!(AbiType::reference(AbiType::unnamed_tuple([])), "ref(tuple)");
1095        assert_eq_sig!(
1096            AbiType::reference(AbiType::unnamed_tuple([AbiType::Address, AbiType::Bool])),
1097            "ref(tuple)"
1098        );
1099        assert_eq_sig!(
1100            AbiType::reference(AbiType::fixedarray(AbiType::Address, 123)),
1101            "ref(address[123])"
1102        );
1103
1104        assert_eq_sig!(
1105            AbiType::array(AbiType::unnamed_tuple([
1106                AbiType::Bool,
1107                AbiType::Uint(123),
1108                AbiType::array(AbiType::map(
1109                    PlainAbiType::Address,
1110                    AbiType::unnamed_tuple([AbiType::Uint(32), AbiType::String]),
1111                )),
1112            ])),
1113            "tuple[]"
1114        );
1115    }
1116
1117    #[test]
1118    fn from_to_json() {
1119        const RAW: &str = r#"{
1120            "name":"info",
1121            "type":"tuple",
1122            "components": [
1123                {"name":"total","type":"uint64"},
1124                {"name":"withdrawValue","type":"uint64"},
1125                {"name":"reinvest","type":"bool"},
1126                {"name":"reward","type":"uint64"},
1127                {"name":"stakes","type":"map(uint64,uint64)"},
1128                {"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)"},
1129                {"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)"},
1130                {"name":"vestingDonor","type":"address"},
1131                {"name":"lockDonor","type":"address"}
1132            ]
1133        }"#;
1134
1135        let ty = serde_json::from_str::<NamedAbiType>(RAW).unwrap();
1136
1137        let complex_item_ty = AbiType::tuple([
1138            ("remainingAmount", u64::abi_type()),
1139            ("lastWithdrawalTime", u64::abi_type()),
1140            ("withdrawalPeriod", u32::abi_type()),
1141            ("withdrawalValue", u64::abi_type()),
1142            ("owner", IntAddr::abi_type()),
1143        ]);
1144
1145        assert_eq!(
1146            ty,
1147            NamedAbiType::new(
1148                "info",
1149                AbiType::Tuple(Arc::from(vec![
1150                    NamedAbiType::new("total", u64::abi_type()),
1151                    NamedAbiType::new("withdrawValue", u64::abi_type()),
1152                    NamedAbiType::new("reinvest", bool::abi_type()),
1153                    NamedAbiType::new("reward", u64::abi_type()),
1154                    NamedAbiType::new("stakes", BTreeMap::<u64, u64>::abi_type()),
1155                    NamedAbiType::new(
1156                        "vestings",
1157                        AbiType::map(u64::plain_abi_type(), complex_item_ty.clone())
1158                    ),
1159                    NamedAbiType::new(
1160                        "locks",
1161                        AbiType::map(u64::plain_abi_type(), complex_item_ty)
1162                    ),
1163                    NamedAbiType::new("vestingDonor", IntAddr::abi_type()),
1164                    NamedAbiType::new("lockDonor", IntAddr::abi_type()),
1165                ]))
1166            )
1167        );
1168
1169        let normalized = serde_json::from_str::<serde_json::Value>(RAW).unwrap();
1170        let serialized = serde_json::to_value(ty).unwrap();
1171        assert_eq!(serialized, normalized);
1172    }
1173}