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