everscale_types/models/message/
address.rs

1use std::str::FromStr;
2
3use crate::cell::*;
4use crate::error::{Error, ParseAddrError};
5use crate::models::block::ShardIdent;
6use crate::num::*;
7use crate::util::*;
8
9/// Basic internal address trait.
10pub trait Addr {
11    /// Returns the workchain part of the address.
12    fn workchain(&self) -> i32;
13    /// Returns the high bits of the address as a number.
14    fn prefix(&self) -> u64;
15}
16
17/// Internal message address.
18#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
19pub enum IntAddr {
20    /// Standard internal address.
21    Std(StdAddr),
22    /// Variable-length internal address.
23    Var(VarAddr),
24}
25
26impl Default for IntAddr {
27    #[inline]
28    fn default() -> Self {
29        Self::Std(StdAddr::default())
30    }
31}
32
33impl IntAddr {
34    /// The maximum number of bits that address occupies.
35    pub const BITS_MAX: u16 = 1 + VarAddr::BITS_MAX;
36
37    /// Returns `true` if this address is for a masterchain block.
38    ///
39    /// See [`ShardIdent::MASTERCHAIN`]
40    #[inline]
41    pub const fn is_masterchain(&self) -> bool {
42        self.workchain() == ShardIdent::MASTERCHAIN.workchain()
43    }
44
45    /// Returns the workchain part of the address.
46    #[inline]
47    pub const fn workchain(&self) -> i32 {
48        match self {
49            Self::Std(addr) => addr.workchain as i32,
50            Self::Var(addr) => addr.workchain,
51        }
52    }
53
54    /// Returns the workchain part of the address.
55    #[inline]
56    pub const fn anycast(&self) -> &Option<Box<Anycast>> {
57        match self {
58            Self::Std(addr) => &addr.anycast,
59            Self::Var(addr) => &addr.anycast,
60        }
61    }
62
63    /// Returns the underlying standard address.
64    #[inline]
65    pub const fn as_std(&self) -> Option<&StdAddr> {
66        match self {
67            Self::Std(addr) => Some(addr),
68            Self::Var(_) => None,
69        }
70    }
71
72    /// Returns the underlying variable-length address.
73    #[inline]
74    pub const fn as_var(&self) -> Option<&VarAddr> {
75        match self {
76            Self::Std(_) => None,
77            Self::Var(addr) => Some(addr),
78        }
79    }
80
81    /// Returns the number of data bits that this struct occupies.
82    pub const fn bit_len(&self) -> u16 {
83        match self {
84            Self::Std(addr) => addr.bit_len(),
85            Self::Var(addr) => addr.bit_len(),
86        }
87    }
88
89    /// Returns the high bits of the address as a number.
90    pub fn prefix(&self) -> u64 {
91        match self {
92            Self::Std(addr) => addr.prefix(),
93            Self::Var(addr) => addr.prefix(),
94        }
95    }
96}
97
98impl Addr for IntAddr {
99    #[inline]
100    fn workchain(&self) -> i32 {
101        IntAddr::workchain(self)
102    }
103
104    #[inline]
105    fn prefix(&self) -> u64 {
106        IntAddr::prefix(self)
107    }
108}
109
110impl From<(i8, HashBytes)> for IntAddr {
111    #[inline]
112    fn from((workchain, address): (i8, HashBytes)) -> Self {
113        IntAddr::Std(StdAddr::new(workchain, address))
114    }
115}
116
117impl FromStr for IntAddr {
118    type Err = ParseAddrError;
119
120    fn from_str(s: &str) -> Result<Self, Self::Err> {
121        // TODO: impl from_str for VarAddr
122        Ok(Self::Std(ok!(StdAddr::from_str(s))))
123    }
124}
125
126impl std::fmt::Display for IntAddr {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        match self {
129            IntAddr::Std(addr) => std::fmt::Display::fmt(addr, f),
130            IntAddr::Var(_) => f.write_str("varaddr"), // TODO: impl display
131        }
132    }
133}
134
135impl Store for IntAddr {
136    fn store_into(
137        &self,
138        builder: &mut CellBuilder,
139        context: &mut dyn CellContext,
140    ) -> Result<(), Error> {
141        match self {
142            Self::Std(addr) => addr.store_into(builder, context),
143            Self::Var(addr) => addr.store_into(builder, context),
144        }
145    }
146}
147
148impl<'a> Load<'a> for IntAddr {
149    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
150        if !ok!(slice.load_bit()) {
151            return Err(Error::InvalidTag);
152        }
153
154        Ok(if unlikely(ok!(slice.load_bit())) {
155            let anycast = ok!(Option::<Box<Anycast>>::load_from(slice));
156            let address_len = ok!(Uint9::load_from(slice));
157            let workchain = ok!(slice.load_u32()) as i32;
158            if !slice.has_remaining(address_len.into_inner(), 0) {
159                return Err(Error::CellUnderflow);
160            }
161
162            let mut address = vec![0; (address_len.into_inner() as usize + 7) / 8];
163            ok!(slice.load_raw(&mut address, address_len.into_inner()));
164
165            Self::Var(VarAddr {
166                anycast,
167                address_len,
168                workchain,
169                address,
170            })
171        } else {
172            Self::Std(StdAddr {
173                anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
174                workchain: ok!(slice.load_u8()) as i8,
175                address: ok!(slice.load_u256()),
176            })
177        })
178    }
179}
180
181#[cfg(feature = "serde")]
182impl serde::Serialize for IntAddr {
183    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
184    where
185        S: serde::Serializer,
186    {
187        match self {
188            Self::Std(addr) => addr.serialize(serializer),
189            Self::Var(_) => {
190                // TODO: impl serde for `VarAddr`
191                serializer.serialize_str("varaddr")
192            }
193        }
194    }
195}
196
197#[cfg(feature = "serde")]
198impl<'de> serde::Deserialize<'de> for IntAddr {
199    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
200    where
201        D: serde::Deserializer<'de>,
202    {
203        // TODO: impl serde for `VarAddr`
204        StdAddr::deserialize(deserializer).map(IntAddr::Std)
205    }
206}
207
208/// Standard internal address.
209#[derive(Debug, Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
210pub struct StdAddr {
211    /// Optional anycast info.
212    pub anycast: Option<Box<Anycast>>,
213    /// Workchain id (one-byte range).
214    pub workchain: i8,
215    /// Account id.
216    pub address: HashBytes,
217}
218
219impl StdAddr {
220    /// The number of data bits that address without anycast occupies.
221    ///
222    /// - 2 bits id (`0b10`)
223    /// - 1 bit Maybe None
224    /// - 8 bits workchain
225    /// - 256 bits address
226    pub const BITS_WITHOUT_ANYCAST: u16 = 2 + 1 + 8 + 256;
227
228    /// The maximum number of bits that address with anycast occupies.
229    pub const BITS_MAX: u16 = Self::BITS_WITHOUT_ANYCAST + Anycast::BITS_MAX;
230
231    /// Constructs a new standard address without anycast info.
232    #[inline]
233    pub const fn new(workchain: i8, address: HashBytes) -> Self {
234        Self {
235            anycast: None,
236            workchain,
237            address,
238        }
239    }
240
241    /// Parses a base64-encoded address.
242    #[cfg(feature = "base64")]
243    pub fn from_str_ext(
244        s: &str,
245        format: StdAddrFormat,
246    ) -> Result<(Self, Base64StdAddrFlags), ParseAddrError> {
247        use base64::prelude::{Engine as _, BASE64_STANDARD, BASE64_URL_SAFE};
248
249        match s.len() {
250            0 => Err(ParseAddrError::Empty),
251            66..=69 if format.allow_raw => Self::from_str(s).map(|addr| (addr, Default::default())),
252            48 if format.allow_base64 || format.allow_base64_url => {
253                let mut buffer = [0u8; 36];
254
255                let base64_url = s.contains(['_', '-']);
256
257                let Ok(36) = if base64_url {
258                    BASE64_URL_SAFE
259                } else {
260                    BASE64_STANDARD
261                }
262                .decode_slice(s, &mut buffer) else {
263                    return Err(ParseAddrError::BadFormat);
264                };
265
266                #[cfg(not(fuzzing))]
267                {
268                    let crc = crc_16(&buffer[..34]);
269                    if buffer[34] as u16 != (crc >> 8) || buffer[35] as u16 != (crc & 0xff) {
270                        return Err(ParseAddrError::BadFormat);
271                    }
272                }
273
274                let addr = StdAddr::new(
275                    buffer[1] as i8,
276                    HashBytes(buffer[2..34].try_into().unwrap()),
277                );
278                let flags = Base64StdAddrFlags {
279                    testnet: buffer[0] & 0x80 != 0,
280                    base64_url,
281                    bounceable: buffer[0] & 0x40 == 0,
282                };
283                Ok((addr, flags))
284            }
285            _ => Err(ParseAddrError::BadFormat),
286        }
287    }
288
289    /// Returns `true` if this address is for a masterchain block.
290    ///
291    /// See [`ShardIdent::MASTERCHAIN`]
292    #[inline]
293    pub const fn is_masterchain(&self) -> bool {
294        self.workchain as i32 == ShardIdent::MASTERCHAIN.workchain()
295    }
296
297    /// Returns the number of data bits that this struct occupies.
298    pub const fn bit_len(&self) -> u16 {
299        let mut bit_len = Self::BITS_WITHOUT_ANYCAST;
300        if let Some(anycast) = &self.anycast {
301            bit_len += anycast.bit_len();
302        }
303        bit_len
304    }
305
306    /// Returns the high bits of the address as a number.
307    pub const fn prefix(&self) -> u64 {
308        u64::from_be_bytes(*self.address.first_chunk())
309    }
310
311    /// Returns a pretty-printer for base64-encoded address.
312    #[cfg(feature = "base64")]
313    pub const fn display_base64(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
314        DisplayBase64StdAddr {
315            addr: self,
316            flags: Base64StdAddrFlags {
317                testnet: false,
318                base64_url: false,
319                bounceable,
320            },
321        }
322    }
323
324    /// Returns a pretty-printer for URL-safe base64-encoded address.
325    #[cfg(feature = "base64")]
326    pub const fn display_base64_url(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
327        DisplayBase64StdAddr {
328            addr: self,
329            flags: Base64StdAddrFlags {
330                testnet: false,
331                base64_url: true,
332                bounceable,
333            },
334        }
335    }
336}
337
338impl Addr for StdAddr {
339    #[inline]
340    fn workchain(&self) -> i32 {
341        self.workchain as i32
342    }
343
344    #[inline]
345    fn prefix(&self) -> u64 {
346        StdAddr::prefix(self)
347    }
348}
349
350impl std::fmt::Display for StdAddr {
351    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
352        if let Some(anycast) = &self.anycast {
353            ok!(f.write_fmt(format_args!("{anycast}:")))
354        }
355
356        f.write_fmt(format_args!("{}:{}", self.workchain, self.address))
357    }
358}
359
360impl From<(i8, HashBytes)> for StdAddr {
361    #[inline]
362    fn from((workchain, address): (i8, HashBytes)) -> Self {
363        Self::new(workchain, address)
364    }
365}
366
367impl From<(i8, [u8; 32])> for StdAddr {
368    #[inline]
369    fn from((workchain, address): (i8, [u8; 32])) -> Self {
370        Self::new(workchain, HashBytes(address))
371    }
372}
373
374impl From<StdAddr> for IntAddr {
375    #[inline]
376    fn from(value: StdAddr) -> Self {
377        Self::Std(value)
378    }
379}
380
381impl FromStr for StdAddr {
382    type Err = ParseAddrError;
383
384    fn from_str(s: &str) -> Result<Self, Self::Err> {
385        if s.is_empty() {
386            return Err(ParseAddrError::Empty);
387        }
388
389        let mut result = Self::default();
390
391        let mut parts = s.split(':');
392        match parts.next() {
393            Some(part) => match part.parse() {
394                Ok(workchain) => result.workchain = workchain,
395                Err(_) => return Err(ParseAddrError::InvalidWorkchain),
396            },
397            None => return Err(ParseAddrError::Empty),
398        }
399
400        match parts.next() {
401            Some(part) => match hex::decode_to_slice(part, &mut result.address.0) {
402                Ok(()) => {}
403                Err(_) => return Err(ParseAddrError::InvalidAccountId),
404            },
405            None => return Err(ParseAddrError::InvalidAccountId),
406        }
407
408        if parts.next().is_none() {
409            Ok(result)
410        } else {
411            Err(ParseAddrError::UnexpectedPart)
412        }
413    }
414}
415
416impl Store for StdAddr {
417    fn store_into(
418        &self,
419        builder: &mut CellBuilder,
420        context: &mut dyn CellContext,
421    ) -> Result<(), Error> {
422        if !builder.has_capacity(self.bit_len(), 0) {
423            return Err(Error::CellOverflow);
424        }
425        ok!(builder.store_small_uint(0b10, 2));
426        ok!(self.anycast.store_into(builder, context));
427        ok!(builder.store_u8(self.workchain as u8));
428        builder.store_u256(&self.address)
429    }
430}
431
432impl<'a> Load<'a> for StdAddr {
433    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
434        if !ok!(slice.load_bit()) || ok!(slice.load_bit()) {
435            return Err(Error::InvalidTag);
436        }
437
438        Ok(Self {
439            anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
440            workchain: ok!(slice.load_u8()) as i8,
441            address: ok!(slice.load_u256()),
442        })
443    }
444}
445
446impl crate::dict::DictKey for StdAddr {
447    const BITS: u16 = StdAddr::BITS_WITHOUT_ANYCAST;
448
449    fn from_raw_data([first_byte, second_byte, data @ ..]: &[u8; 128]) -> Option<Self> {
450        // 2 bits id, 1 bit maybe (None), 8 bits workchain, 256 bits address
451
452        const PREFIX_BITS: u8 = 0b1000_0000;
453        const PREFIX_MASK: u8 = 0b1110_0000;
454
455        const R: u8 = 3;
456        const SHIFT: u8 = 8 - R;
457        const REV_SHIFT: u8 = 120 + R;
458
459        if unlikely((first_byte ^ PREFIX_BITS) & PREFIX_MASK != 0) {
460            return None;
461        }
462
463        let mut result = Self {
464            anycast: None,
465            // 100xxxxx | xxxaaaaa -> xxxxxxxx
466            workchain: ((first_byte << R) | (second_byte >> SHIFT)) as i8,
467            address: HashBytes::ZERO,
468        };
469
470        // SAFETY: transmuting [u8; 32] to [u128; 2] is safe
471        let [mut hi, mut lo]: [u128; 2] =
472            unsafe { std::mem::transmute::<[u8; 32], _>(data[..32].try_into().unwrap()) };
473
474        // Numbers are in big endian order, swap bytes on little endian arch
475        #[cfg(target_endian = "little")]
476        {
477            hi = hi.swap_bytes();
478            lo = lo.swap_bytes();
479        }
480
481        // SAFETY: transmuting [[u8; 16]; 2] to [u8; 32] is safe
482        result.address = unsafe {
483            std::mem::transmute::<[[u8; 16]; 2], HashBytes>([
484                (hi >> SHIFT | ((*second_byte as u128) << REV_SHIFT)).to_be_bytes(),
485                (lo >> SHIFT | (hi << REV_SHIFT)).to_be_bytes(),
486            ])
487        };
488
489        Some(result)
490    }
491}
492
493#[cfg(feature = "serde")]
494impl serde::Serialize for StdAddr {
495    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
496    where
497        S: serde::Serializer,
498    {
499        if serializer.is_human_readable() {
500            serializer.collect_str(self)
501        } else {
502            (self.workchain, &self.address).serialize(serializer)
503        }
504    }
505}
506
507#[cfg(feature = "serde")]
508impl<'de> serde::Deserialize<'de> for StdAddr {
509    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
510    where
511        D: serde::Deserializer<'de>,
512    {
513        use serde::de::{Error, Visitor};
514
515        struct StdAddrVisitor;
516
517        impl<'de> Visitor<'de> for StdAddrVisitor {
518            type Value = StdAddr;
519
520            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
521                f.write_str("a standard address")
522            }
523
524            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
525            where
526                E: Error,
527            {
528                StdAddr::from_str(v).map_err(E::custom)
529            }
530        }
531
532        if deserializer.is_human_readable() {
533            deserializer.deserialize_str(StdAddrVisitor)
534        } else {
535            <(i8, HashBytes)>::deserialize(deserializer)
536                .map(|(workchain, address)| Self::new(workchain, address))
537        }
538    }
539}
540
541/// A helper struct to work with base64-encoded addresses.
542#[cfg(feature = "base64")]
543pub struct StdAddrBase64Repr<const URL_SAFE: bool = true>;
544
545#[cfg(all(feature = "base64", feature = "serde"))]
546impl<const URL_SAFE: bool> StdAddrBase64Repr<URL_SAFE> {
547    /// Serializes address into a base64-encoded string.
548    pub fn serialize<S>(addr: &StdAddr, serializer: S) -> Result<S::Ok, S::Error>
549    where
550        S: serde::Serializer,
551    {
552        serializer.collect_str(&DisplayBase64StdAddr {
553            addr,
554            flags: Base64StdAddrFlags {
555                testnet: false,
556                base64_url: URL_SAFE,
557                bounceable: false,
558            },
559        })
560    }
561
562    /// Deserializes address as a base64-encoded string.
563    pub fn deserialize<'de, D>(deserializer: D) -> Result<StdAddr, D::Error>
564    where
565        D: serde::Deserializer<'de>,
566    {
567        use serde::de::{Error, Visitor};
568
569        struct StdAddrBase64Visitor;
570
571        impl<'de> Visitor<'de> for StdAddrBase64Visitor {
572            type Value = StdAddr;
573
574            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
575                f.write_str("a standard address")
576            }
577
578            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
579            where
580                E: Error,
581            {
582                StdAddr::from_str_ext(v, StdAddrFormat::any())
583                    .map(|(addr, _)| addr)
584                    .map_err(E::custom)
585            }
586        }
587
588        deserializer.deserialize_str(StdAddrBase64Visitor)
589    }
590}
591
592/// Parsing options for [`StdAddr::from_str_ext`]
593#[cfg(feature = "base64")]
594#[derive(Debug, Clone, Copy)]
595pub struct StdAddrFormat {
596    /// Allow raw address (0:000...000).
597    pub allow_raw: bool,
598    /// Allow base64-encoded address.
599    pub allow_base64: bool,
600    /// Allow URL-safe base64 encoding.
601    pub allow_base64_url: bool,
602}
603
604#[cfg(feature = "base64")]
605impl StdAddrFormat {
606    /// Allows any address format.
607    pub const fn any() -> Self {
608        StdAddrFormat {
609            allow_raw: true,
610            allow_base64: true,
611            allow_base64_url: true,
612        }
613    }
614}
615
616/// Base64-encoded address flags.
617#[cfg(feature = "base64")]
618#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
619pub struct Base64StdAddrFlags {
620    /// Address belongs to testnet.
621    pub testnet: bool,
622    /// Use URL-safe base64 encoding.
623    pub base64_url: bool,
624    /// Whether to set `bounce` flag during transfer.
625    pub bounceable: bool,
626}
627
628/// Pretty-printer for [`StdAddr`] in base64 format.
629#[cfg(feature = "base64")]
630pub struct DisplayBase64StdAddr<'a> {
631    /// Address to display.
632    pub addr: &'a StdAddr,
633    /// Encoding flags.
634    pub flags: Base64StdAddrFlags,
635}
636
637#[cfg(feature = "base64")]
638impl std::fmt::Display for DisplayBase64StdAddr<'_> {
639    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
640        use base64::prelude::{Engine as _, BASE64_STANDARD, BASE64_URL_SAFE};
641
642        let mut buffer = [0u8; 36];
643        buffer[0] = (0x51 - (self.flags.bounceable as i32) * 0x40
644            + (self.flags.testnet as i32) * 0x80) as u8;
645        buffer[1] = self.addr.workchain as u8;
646        buffer[2..34].copy_from_slice(self.addr.address.as_array());
647
648        let crc = crc_16(&buffer[..34]);
649        buffer[34] = (crc >> 8) as u8;
650        buffer[35] = (crc & 0xff) as u8;
651
652        let mut output = [0u8; 48];
653        if self.flags.base64_url {
654            BASE64_URL_SAFE
655        } else {
656            BASE64_STANDARD
657        }
658        .encode_slice(buffer, &mut output)
659        .unwrap();
660
661        // SAFETY: output is guaranteed to contain only ASCII.
662        let output = unsafe { std::str::from_utf8_unchecked(&output) };
663        f.write_str(output)
664    }
665}
666
667/// Variable-length internal address.
668#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
669pub struct VarAddr {
670    /// Optional anycast info.
671    pub anycast: Option<Box<Anycast>>,
672    /// Address length in bits.
673    pub address_len: Uint9,
674    /// Workchain id (full range).
675    pub workchain: i32,
676    /// Variable-length address.
677    pub address: Vec<u8>,
678}
679
680impl VarAddr {
681    /// The maximum number of bits that address occupies.
682    ///
683    /// - 2 bits id (`0b11`)
684    /// - 1 + `Anycast::BITS_MAX` maybe anycast
685    /// - 9 bits `address_len`
686    /// - 32 bits workchain
687    /// - `address_len` bits of address
688    pub const BITS_MAX: u16 =
689        2 + 1 + Anycast::BITS_MAX + Uint9::BITS + 32 + Uint9::MAX.into_inner();
690
691    /// Returns `true` if this address is for a masterchain block.
692    ///
693    /// See [`ShardIdent::MASTERCHAIN`]
694    #[inline]
695    pub const fn is_masterchain(&self) -> bool {
696        self.workchain == ShardIdent::MASTERCHAIN.workchain()
697    }
698
699    /// Returns the number of data bits that this struct occupies.
700    pub const fn bit_len(&self) -> u16 {
701        let mut bit_len = 2 + 1 + Uint9::BITS + 32 + self.address_len.into_inner();
702        if let Some(anycast) = &self.anycast {
703            bit_len += anycast.bit_len();
704        }
705        bit_len
706    }
707
708    /// Returns the high bits of the address as a number.
709    pub fn prefix(&self) -> u64 {
710        let mut prefix = [0; 8];
711        let total_bytes = std::cmp::min(self.address.len(), 8);
712        prefix[..total_bytes].copy_from_slice(&self.address[..total_bytes]);
713        u64::from_be_bytes(prefix)
714    }
715}
716
717impl From<VarAddr> for IntAddr {
718    #[inline]
719    fn from(value: VarAddr) -> Self {
720        Self::Var(value)
721    }
722}
723
724impl Store for VarAddr {
725    fn store_into(
726        &self,
727        builder: &mut CellBuilder,
728        context: &mut dyn CellContext,
729    ) -> Result<(), Error> {
730        if !builder.has_capacity(self.bit_len(), 0) {
731            return Err(Error::CellOverflow);
732        }
733        ok!(builder.store_small_uint(0b11, 2));
734        ok!(self.anycast.store_into(builder, context));
735        ok!(self.address_len.store_into(builder, context));
736        ok!(builder.store_u32(self.workchain as u32));
737        builder.store_raw(&self.address, self.address_len.into_inner())
738    }
739}
740
741impl Addr for VarAddr {
742    #[inline]
743    fn workchain(&self) -> i32 {
744        self.workchain
745    }
746
747    #[inline]
748    fn prefix(&self) -> u64 {
749        VarAddr::prefix(self)
750    }
751}
752
753/// External address.
754///
755/// ```text
756/// addr_none$00 = MsgAddressExt;
757/// addr_extern$01 len:(## 9) external_address:(bits len) = MsgAddressExt;
758/// ```
759#[derive(Debug, Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
760pub struct ExtAddr {
761    /// Number of bits stored in data.
762    pub data_bit_len: Uint9,
763    /// External address data
764    pub data: Vec<u8>,
765}
766
767impl ExtAddr {
768    /// Creates non-empty external address.
769    pub fn new<T>(data_bit_len: u16, data: T) -> Option<Self>
770    where
771        T: Into<Vec<u8>>,
772    {
773        let data_bit_len = Uint9::new(data_bit_len);
774        if data_bit_len.is_valid() {
775            Some(Self {
776                data_bit_len,
777                data: data.into(),
778            })
779        } else {
780            None
781        }
782    }
783
784    /// Returns the number of data bits that this struct occupies.
785    pub const fn bit_len(&self) -> u16 {
786        Uint9::BITS + self.data_bit_len.into_inner()
787    }
788}
789
790impl std::fmt::Display for ExtAddr {
791    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
792        let bitstring = Bitstring {
793            bytes: &self.data,
794            bit_len: self.data_bit_len.into_inner(),
795        };
796        write!(f, ":{bitstring}")
797    }
798}
799
800impl FromStr for ExtAddr {
801    type Err = ParseAddrError;
802
803    fn from_str(s: &str) -> Result<Self, Self::Err> {
804        if s.is_empty() {
805            return Err(ParseAddrError::Empty);
806        }
807
808        let Some(s) = s.strip_prefix(':') else {
809            return Err(ParseAddrError::UnexpectedPart);
810        };
811
812        let Ok((data, bit_len)) = Bitstring::from_hex_str(s) else {
813            return Err(ParseAddrError::InvalidAccountId);
814        };
815
816        ExtAddr::new(bit_len, data).ok_or(ParseAddrError::UnexpectedPart)
817    }
818}
819
820#[cfg(feature = "serde")]
821impl serde::Serialize for ExtAddr {
822    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
823        if serializer.is_human_readable() {
824            serializer.collect_str(self)
825        } else {
826            (self.data_bit_len.into_inner(), &self.data).serialize(serializer)
827        }
828    }
829}
830
831#[cfg(feature = "serde")]
832impl<'de> serde::Deserialize<'de> for ExtAddr {
833    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
834        use serde::de::{Error, Visitor};
835
836        struct ExtAddrVisitor;
837
838        impl<'de> Visitor<'de> for ExtAddrVisitor {
839            type Value = ExtAddr;
840
841            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
842                f.write_str("an external address")
843            }
844
845            fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
846                ExtAddr::from_str(v).map_err(E::custom)
847            }
848        }
849
850        if deserializer.is_human_readable() {
851            deserializer.deserialize_str(ExtAddrVisitor)
852        } else {
853            <(u16, Vec<u8>)>::deserialize(deserializer).and_then(|(data_bit_len, data)| {
854                ExtAddr::new(data_bit_len, data)
855                    .ok_or_else(|| Error::custom("invalid external address data length"))
856            })
857        }
858    }
859}
860
861/// Anycast prefix info.
862///
863/// ```text
864/// anycast_info$_ depth:(#<= 30) { depth >= 1 } rewrite_pfx:(bits depth) = Anycast;
865/// ```
866#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
867pub struct Anycast {
868    /// Prefix length in bits.
869    pub depth: SplitDepth,
870    /// Rewrite prefix data.
871    pub rewrite_prefix: Vec<u8>,
872}
873
874impl Anycast {
875    /// The minimum allowed number of bits in the rewrite prefix.
876    pub const MIN_DEPTH: u8 = 1;
877    /// The maximum allowed number of bits in the rewrite prefix.
878    pub const MAX_DEPTH: u8 = 30;
879
880    /// The maximum number of bits that an Anycast occupies.
881    pub const BITS_MAX: u16 = SplitDepth::BITS + Self::MAX_DEPTH as u16;
882
883    /// Constructs anycast info from rewrite prefix.
884    pub fn from_slice(rewrite_prefix: &CellSlice<'_>) -> Result<Self, Error> {
885        let depth = ok!(SplitDepth::from_bit_len(rewrite_prefix.size_bits()));
886
887        let mut data = vec![0; (depth.into_bit_len() as usize + 7) / 8];
888        ok!(rewrite_prefix.get_raw(0, &mut data, depth.into_bit_len()));
889
890        Ok(Self {
891            depth,
892            rewrite_prefix: data,
893        })
894    }
895
896    /// Returns the number of data bits that this struct occupies.
897    pub const fn bit_len(&self) -> u16 {
898        SplitDepth::BITS + self.depth.into_bit_len()
899    }
900}
901
902impl std::fmt::Display for Anycast {
903    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
904        let bitstring = Bitstring {
905            bytes: &self.rewrite_prefix,
906            bit_len: self.depth.into_bit_len(),
907        };
908        std::fmt::Display::fmt(&bitstring, f)
909    }
910}
911
912impl Store for Anycast {
913    fn store_into(
914        &self,
915        builder: &mut CellBuilder,
916        context: &mut dyn CellContext,
917    ) -> Result<(), Error> {
918        if !builder.has_capacity(self.bit_len(), 0) {
919            return Err(Error::CellOverflow);
920        }
921        ok!(self.depth.store_into(builder, context));
922        builder.store_raw(&self.rewrite_prefix, self.depth.into_bit_len())
923    }
924}
925
926impl<'a> Load<'a> for Anycast {
927    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
928        let depth = ok!(SplitDepth::load_from(slice));
929        if !slice.has_remaining(depth.into_bit_len(), 0) {
930            return Err(Error::CellUnderflow);
931        }
932
933        let mut rewrite_prefix = vec![0; (depth.into_bit_len() as usize + 7) / 8];
934        ok!(slice.load_raw(&mut rewrite_prefix, depth.into_bit_len()));
935
936        Ok(Self {
937            depth,
938            rewrite_prefix,
939        })
940    }
941}
942
943#[cfg(test)]
944mod tests {
945    use super::*;
946    use crate::dict::Dict;
947
948    #[test]
949    fn dict_with_std_addr_keys() {
950        let mut dict = Dict::<StdAddr, u32>::new();
951        dict.set(StdAddr::new(-1, HashBytes([0x33; 32])), 123)
952            .unwrap();
953        dict.set(StdAddr::new(0, HashBytes([0x10; 32])), 321)
954            .unwrap();
955        dict.set(StdAddr::new(-1, HashBytes([0x55; 32])), 234)
956            .unwrap();
957        dict.set(StdAddr::new(0, HashBytes([0x20; 32])), 432)
958            .unwrap();
959
960        for entry in dict.iter() {
961            let (addr, value) = entry.unwrap();
962            println!("{addr}: {value}");
963        }
964    }
965
966    #[test]
967    fn anycast_str() {
968        // 0 bit
969        let empty_res = Anycast::from_slice(&Cell::empty_cell().as_slice().unwrap());
970        assert_eq!(empty_res.unwrap_err(), Error::IntOverflow);
971
972        // 1 bit
973        let mut prefix = CellBuilder::new();
974        prefix.store_bit_one().unwrap();
975        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
976        assert_eq!(anycast.to_string(), "c_");
977
978        // 8 bit
979        let mut prefix = CellBuilder::new();
980        prefix.store_u8(0xa5).unwrap();
981        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
982        assert_eq!(anycast.to_string(), "a5");
983
984        // 30 bit
985        let mut prefix = CellBuilder::new();
986        prefix.store_uint(0xb00b1e5, 28).unwrap();
987        prefix.store_zeros(2).unwrap();
988        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
989        assert_eq!(anycast.to_string(), "b00b1e52_");
990    }
991
992    #[test]
993    fn address_prefix() {
994        let addr = "0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415"
995            .parse::<StdAddr>()
996            .unwrap();
997        assert_eq!(addr.prefix(), 0xece57bcc6c530283);
998
999        let var_addr = VarAddr {
1000            anycast: None,
1001            address_len: Uint9::new(32),
1002            workchain: 0,
1003            address: vec![0xb0, 0xba, 0xca, 0xfe],
1004        };
1005        assert_eq!(var_addr.prefix(), 0xb0bacafe00000000);
1006
1007        let var_addr = VarAddr {
1008            anycast: None,
1009            address_len: Uint9::new(72),
1010            workchain: 0,
1011            address: vec![0xb0, 0xba, 0xca, 0xfe, 0xb0, 0x0b, 0x1e, 0x5a, 0xff],
1012        };
1013        assert_eq!(var_addr.prefix(), 0xb0bacafeb00b1e5a);
1014    }
1015
1016    #[test]
1017    fn base64_address() {
1018        let addr = "0:84545d4d2cada0ce811705d534c298ca42d29315d03a16eee794cefd191dfa79"
1019            .parse::<StdAddr>()
1020            .unwrap();
1021        assert_eq!(
1022            addr.display_base64(true).to_string(),
1023            "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw"
1024        );
1025        assert_eq!(
1026            StdAddr::from_str_ext(
1027                "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw",
1028                StdAddrFormat::any()
1029            )
1030            .unwrap(),
1031            (
1032                addr,
1033                Base64StdAddrFlags {
1034                    testnet: false,
1035                    base64_url: false,
1036                    bounceable: true,
1037                }
1038            )
1039        );
1040
1041        let addr = "0:dddde93b1d3398f0b4305c08de9a032e0bc1b257c4ce2c72090aea1ff3e9ecfd"
1042            .parse::<StdAddr>()
1043            .unwrap();
1044        assert_eq!(
1045            addr.display_base64_url(false).to_string(),
1046            "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_Tyv"
1047        );
1048        assert_eq!(
1049            addr.display_base64(false).to_string(),
1050            "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv"
1051        );
1052
1053        assert_eq!(
1054            StdAddr::from_str_ext(
1055                "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv",
1056                StdAddrFormat::any()
1057            )
1058            .unwrap(),
1059            (
1060                addr.clone(),
1061                Base64StdAddrFlags {
1062                    testnet: false,
1063                    base64_url: false,
1064                    bounceable: false,
1065                }
1066            )
1067        );
1068
1069        assert_eq!(
1070            addr.display_base64_url(true).to_string(),
1071            "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq"
1072        );
1073        assert_eq!(
1074            addr.display_base64(true).to_string(),
1075            "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/WFq"
1076        );
1077
1078        assert_eq!(
1079            StdAddr::from_str_ext(
1080                "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq",
1081                StdAddrFormat::any()
1082            )
1083            .unwrap(),
1084            (
1085                addr,
1086                Base64StdAddrFlags {
1087                    testnet: false,
1088                    base64_url: true,
1089                    bounceable: true,
1090                }
1091            )
1092        );
1093    }
1094}