1use std::str::FromStr;
2
3use crate::cell::*;
4use crate::error::{Error, ParseAddrError};
5use crate::models::block::ShardIdent;
6use crate::models::message::{load_ext_addr, store_ext_addr};
7use crate::num::*;
8use crate::util::*;
9
10pub trait Addr {
12 fn workchain(&self) -> i32;
14 fn prefix(&self) -> u64;
16}
17
18#[derive(Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
20pub enum AnyAddr {
21 #[default]
23 None,
24 Ext(ExtAddr),
26 Std(StdAddr),
28 Var(VarAddr),
30}
31
32impl AnyAddr {
33 pub fn bit_len(&self) -> u16 {
35 match self {
36 AnyAddr::None => 2, AnyAddr::Ext(addr) => addr.bit_len(),
38 AnyAddr::Std(addr) => addr.bit_len(),
39 AnyAddr::Var(addr) => addr.bit_len(),
40 }
41 }
42}
43
44impl Store for AnyAddr {
45 fn store_into(
46 &self,
47 builder: &mut CellBuilder,
48 context: &dyn CellContext,
49 ) -> Result<(), Error> {
50 match self {
51 Self::None => store_ext_addr(builder, context, &None),
52 Self::Std(addr) => addr.store_into(builder, context),
53 Self::Var(addr) => addr.store_into(builder, context),
54 Self::Ext(addr) => store_ext_addr(builder, context, &Some(addr.clone())),
55 }
56 }
57}
58
59impl<'a> Load<'a> for AnyAddr {
60 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
61 let addr = if ok!(slice.get_bit(0)) {
62 let addr = ok!(IntAddr::load_from(slice));
63 match addr {
64 IntAddr::Std(addr) => Self::Std(addr),
65 IntAddr::Var(addr) => Self::Var(addr),
66 }
67 } else {
68 match ok!(load_ext_addr(slice)) {
69 Some(addr) => Self::Ext(addr),
70 None => Self::None,
71 }
72 };
73
74 Ok(addr)
75 }
76}
77
78impl From<Option<ExtAddr>> for AnyAddr {
80 fn from(value: Option<ExtAddr>) -> Self {
81 if let Some(addr) = value {
82 AnyAddr::Ext(addr)
83 } else {
84 AnyAddr::None
85 }
86 }
87}
88
89impl From<Option<IntAddr>> for AnyAddr {
90 fn from(value: Option<IntAddr>) -> Self {
91 match value {
92 Some(IntAddr::Std(addr)) => AnyAddr::Std(addr),
93 Some(IntAddr::Var(addr)) => AnyAddr::Var(addr),
94 None => AnyAddr::None,
95 }
96 }
97}
98
99impl From<IntAddr> for AnyAddr {
100 fn from(value: IntAddr) -> Self {
101 match value {
102 IntAddr::Std(addr) => AnyAddr::Std(addr),
103 IntAddr::Var(addr) => AnyAddr::Var(addr),
104 }
105 }
106}
107
108impl From<ExtAddr> for AnyAddr {
109 fn from(value: ExtAddr) -> Self {
110 AnyAddr::Ext(value)
111 }
112}
113
114impl From<StdAddr> for AnyAddr {
115 fn from(value: StdAddr) -> Self {
116 AnyAddr::Std(value)
117 }
118}
119
120impl From<VarAddr> for AnyAddr {
121 fn from(value: VarAddr) -> Self {
122 AnyAddr::Var(value)
123 }
124}
125
126#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
128pub enum IntAddr {
129 Std(StdAddr),
131 Var(VarAddr),
133}
134
135impl Default for IntAddr {
136 #[inline]
137 fn default() -> Self {
138 Self::Std(StdAddr::default())
139 }
140}
141
142impl IntAddr {
143 pub const BITS_MAX: u16 = 1 + VarAddr::BITS_MAX;
145
146 #[inline]
150 pub const fn is_masterchain(&self) -> bool {
151 self.workchain() == ShardIdent::MASTERCHAIN.workchain()
152 }
153
154 #[inline]
156 pub const fn workchain(&self) -> i32 {
157 match self {
158 Self::Std(addr) => addr.workchain as i32,
159 Self::Var(addr) => addr.workchain,
160 }
161 }
162
163 #[inline]
165 pub const fn anycast(&self) -> &Option<Box<Anycast>> {
166 match self {
167 Self::Std(addr) => &addr.anycast,
168 Self::Var(addr) => &addr.anycast,
169 }
170 }
171
172 #[inline]
174 pub const fn as_std(&self) -> Option<&StdAddr> {
175 match self {
176 Self::Std(addr) => Some(addr),
177 Self::Var(_) => None,
178 }
179 }
180
181 #[inline]
183 pub const fn as_var(&self) -> Option<&VarAddr> {
184 match self {
185 Self::Std(_) => None,
186 Self::Var(addr) => Some(addr),
187 }
188 }
189
190 pub const fn bit_len(&self) -> u16 {
192 match self {
193 Self::Std(addr) => addr.bit_len(),
194 Self::Var(addr) => addr.bit_len(),
195 }
196 }
197
198 pub fn prefix(&self) -> u64 {
200 match self {
201 Self::Std(addr) => addr.prefix(),
202 Self::Var(addr) => addr.prefix(),
203 }
204 }
205}
206
207impl Addr for IntAddr {
208 #[inline]
209 fn workchain(&self) -> i32 {
210 IntAddr::workchain(self)
211 }
212
213 #[inline]
214 fn prefix(&self) -> u64 {
215 IntAddr::prefix(self)
216 }
217}
218
219impl From<(i8, HashBytes)> for IntAddr {
220 #[inline]
221 fn from((workchain, address): (i8, HashBytes)) -> Self {
222 IntAddr::Std(StdAddr::new(workchain, address))
223 }
224}
225
226impl FromStr for IntAddr {
227 type Err = ParseAddrError;
228
229 fn from_str(s: &str) -> Result<Self, Self::Err> {
230 Ok(Self::Std(ok!(StdAddr::from_str(s))))
232 }
233}
234
235impl std::fmt::Display for IntAddr {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 match self {
238 IntAddr::Std(addr) => std::fmt::Display::fmt(addr, f),
239 IntAddr::Var(_) => f.write_str("varaddr"), }
241 }
242}
243
244impl Store for IntAddr {
245 fn store_into(
246 &self,
247 builder: &mut CellBuilder,
248 context: &dyn CellContext,
249 ) -> Result<(), Error> {
250 match self {
251 Self::Std(addr) => addr.store_into(builder, context),
252 Self::Var(addr) => addr.store_into(builder, context),
253 }
254 }
255}
256
257impl<'a> Load<'a> for IntAddr {
258 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
259 if !ok!(slice.load_bit()) {
260 return Err(Error::InvalidTag);
261 }
262
263 Ok(if unlikely(ok!(slice.load_bit())) {
264 let anycast = ok!(Option::<Box<Anycast>>::load_from(slice));
265 let address_len = ok!(Uint9::load_from(slice));
266 let workchain = ok!(slice.load_u32()) as i32;
267 if !slice.has_remaining(address_len.into_inner(), 0) {
268 return Err(Error::CellUnderflow);
269 }
270
271 let mut address = vec![0; address_len.into_inner().div_ceil(8) as usize];
272 ok!(slice.load_raw(&mut address, address_len.into_inner()));
273
274 Self::Var(VarAddr {
275 anycast,
276 address_len,
277 workchain,
278 address,
279 })
280 } else {
281 Self::Std(StdAddr {
282 anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
283 workchain: ok!(slice.load_u8()) as i8,
284 address: ok!(slice.load_u256()),
285 })
286 })
287 }
288}
289
290#[cfg(feature = "serde")]
291impl serde::Serialize for IntAddr {
292 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
293 where
294 S: serde::Serializer,
295 {
296 match self {
297 Self::Std(addr) => addr.serialize(serializer),
298 Self::Var(_) => {
299 serializer.serialize_str("varaddr")
301 }
302 }
303 }
304}
305
306#[cfg(feature = "serde")]
307impl<'de> serde::Deserialize<'de> for IntAddr {
308 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
309 where
310 D: serde::Deserializer<'de>,
311 {
312 StdAddr::deserialize(deserializer).map(IntAddr::Std)
314 }
315}
316
317#[cfg(feature = "arbitrary")]
318impl<'a> arbitrary::Arbitrary<'a> for IntAddr {
319 #[inline]
320 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
321 if u.ratio(1u8, 20u8)? {
322 u.arbitrary().map(Self::Var)
323 } else {
324 u.arbitrary().map(Self::Std)
325 }
326 }
327
328 #[inline]
329 fn size_hint(depth: usize) -> (usize, Option<usize>) {
330 Self::try_size_hint(depth).unwrap_or_default()
331 }
332
333 #[inline]
334 fn try_size_hint(
335 depth: usize,
336 ) -> Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
337 Ok(arbitrary::size_hint::and(
338 <u8 as arbitrary::Arbitrary>::try_size_hint(depth)?,
339 arbitrary::size_hint::or(StdAddr::size_hint(depth), VarAddr::size_hint(depth)),
340 ))
341 }
342}
343
344#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
346pub struct StdAddr {
347 pub anycast: Option<Box<Anycast>>,
349 pub workchain: i8,
351 pub address: HashBytes,
353}
354
355impl StdAddr {
356 pub const BITS_WITHOUT_ANYCAST: u16 = 2 + 1 + 8 + 256;
363
364 pub const BITS_MAX: u16 = Self::BITS_WITHOUT_ANYCAST + Anycast::BITS_MAX;
366
367 pub const ZERO: Self = Self::new(0, HashBytes::ZERO);
371
372 #[inline]
374 pub const fn new(workchain: i8, address: HashBytes) -> Self {
375 Self {
376 anycast: None,
377 workchain,
378 address,
379 }
380 }
381
382 #[cfg(feature = "base64")]
384 pub fn from_str_ext(
385 s: &str,
386 format: StdAddrFormat,
387 ) -> Result<(Self, Base64StdAddrFlags), ParseAddrError> {
388 use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE, Engine as _};
389
390 match s.len() {
391 0 => Err(ParseAddrError::Empty),
392 66..=69 if format.allow_raw => Self::from_str(s).map(|addr| (addr, Default::default())),
393 48 if format.allow_base64 || format.allow_base64_url => {
394 let mut buffer = [0u8; 36];
395
396 let base64_url = s.contains(['_', '-']);
397
398 let Ok(36) = if base64_url {
399 BASE64_URL_SAFE
400 } else {
401 BASE64_STANDARD
402 }
403 .decode_slice(s, &mut buffer) else {
404 return Err(ParseAddrError::BadFormat);
405 };
406
407 #[cfg(not(fuzzing))]
408 {
409 let crc = crate::crc::crc_16(&buffer[..34]);
410 if buffer[34] as u16 != (crc >> 8) || buffer[35] as u16 != (crc & 0xff) {
411 return Err(ParseAddrError::BadFormat);
412 }
413 }
414
415 let addr = StdAddr::new(
416 buffer[1] as i8,
417 HashBytes(buffer[2..34].try_into().unwrap()),
418 );
419 let flags = Base64StdAddrFlags {
420 testnet: buffer[0] & 0x80 != 0,
421 base64_url,
422 bounceable: buffer[0] & 0x40 == 0,
423 };
424 Ok((addr, flags))
425 }
426 _ => Err(ParseAddrError::BadFormat),
427 }
428 }
429
430 #[inline]
434 pub const fn is_masterchain(&self) -> bool {
435 self.workchain as i32 == ShardIdent::MASTERCHAIN.workchain()
436 }
437
438 pub const fn is_zero(&self) -> bool {
440 self.workchain == 0 && self.anycast.is_none() && self.address.is_zero()
441 }
442
443 pub const fn bit_len(&self) -> u16 {
445 let mut bit_len = Self::BITS_WITHOUT_ANYCAST;
446 if let Some(anycast) = &self.anycast {
447 bit_len += anycast.bit_len();
448 }
449 bit_len
450 }
451
452 pub const fn prefix(&self) -> u64 {
454 u64::from_be_bytes(*self.address.first_chunk())
455 }
456
457 #[cfg(feature = "base64")]
459 pub const fn display_base64(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
460 DisplayBase64StdAddr {
461 addr: self,
462 flags: Base64StdAddrFlags {
463 testnet: false,
464 base64_url: false,
465 bounceable,
466 },
467 }
468 }
469
470 #[cfg(feature = "base64")]
472 pub const fn display_base64_url(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
473 DisplayBase64StdAddr {
474 addr: self,
475 flags: Base64StdAddrFlags {
476 testnet: false,
477 base64_url: true,
478 bounceable,
479 },
480 }
481 }
482}
483
484impl Default for StdAddr {
485 #[inline]
486 fn default() -> Self {
487 Self::ZERO
488 }
489}
490
491impl Addr for StdAddr {
492 #[inline]
493 fn workchain(&self) -> i32 {
494 self.workchain as i32
495 }
496
497 #[inline]
498 fn prefix(&self) -> u64 {
499 StdAddr::prefix(self)
500 }
501}
502
503impl std::fmt::Display for StdAddr {
504 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
505 if let Some(anycast) = &self.anycast {
506 ok!(f.write_fmt(format_args!("{anycast}:")))
507 }
508
509 f.write_fmt(format_args!("{}:{}", self.workchain, self.address))
510 }
511}
512
513impl From<(i8, HashBytes)> for StdAddr {
514 #[inline]
515 fn from((workchain, address): (i8, HashBytes)) -> Self {
516 Self::new(workchain, address)
517 }
518}
519
520impl From<(i8, [u8; 32])> for StdAddr {
521 #[inline]
522 fn from((workchain, address): (i8, [u8; 32])) -> Self {
523 Self::new(workchain, HashBytes(address))
524 }
525}
526
527impl From<StdAddr> for IntAddr {
528 #[inline]
529 fn from(value: StdAddr) -> Self {
530 Self::Std(value)
531 }
532}
533
534impl FromStr for StdAddr {
535 type Err = ParseAddrError;
536
537 fn from_str(s: &str) -> Result<Self, Self::Err> {
538 if s.is_empty() {
539 return Err(ParseAddrError::Empty);
540 }
541
542 let mut result = Self::default();
543
544 let mut parts = s.split(':');
545 match parts.next() {
546 Some(part) => match part.parse() {
547 Ok(workchain) => result.workchain = workchain,
548 Err(_) => return Err(ParseAddrError::InvalidWorkchain),
549 },
550 None => return Err(ParseAddrError::Empty),
551 }
552
553 match parts.next() {
554 Some(part) => match hex::decode_to_slice(part, &mut result.address.0) {
555 Ok(()) => {}
556 Err(_) => return Err(ParseAddrError::InvalidAccountId),
557 },
558 None => return Err(ParseAddrError::InvalidAccountId),
559 }
560
561 if parts.next().is_none() {
562 Ok(result)
563 } else {
564 Err(ParseAddrError::UnexpectedPart)
565 }
566 }
567}
568
569impl Store for StdAddr {
570 fn store_into(
571 &self,
572 builder: &mut CellBuilder,
573 context: &dyn CellContext,
574 ) -> Result<(), Error> {
575 if !builder.has_capacity(self.bit_len(), 0) {
576 return Err(Error::CellOverflow);
577 }
578 ok!(builder.store_small_uint(0b10, 2));
579 ok!(self.anycast.store_into(builder, context));
580 ok!(builder.store_u8(self.workchain as u8));
581 builder.store_u256(&self.address)
582 }
583}
584
585impl<'a> Load<'a> for StdAddr {
586 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
587 if !ok!(slice.load_bit()) || ok!(slice.load_bit()) {
588 return Err(Error::InvalidTag);
589 }
590
591 Ok(Self {
592 anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
593 workchain: ok!(slice.load_u8()) as i8,
594 address: ok!(slice.load_u256()),
595 })
596 }
597}
598
599impl crate::dict::DictKey for StdAddr {
600 const BITS: u16 = StdAddr::BITS_WITHOUT_ANYCAST;
601}
602
603impl crate::dict::StoreDictKey for StdAddr {
604 fn store_into_data(&self, builder: &mut CellDataBuilder) -> Result<(), Error> {
605 if self.anycast.is_some() || !builder.has_capacity_bits(Self::BITS_WITHOUT_ANYCAST) {
606 return Err(Error::InvalidData);
607 }
608 ok!(builder.store_small_uint(0b100, 3)); ok!(builder.store_u8(self.workchain as u8));
610 builder.store_u256(&self.address)
611 }
612}
613
614impl crate::dict::LoadDictKey for StdAddr {
615 fn load_from_data(data: &CellDataBuilder) -> Option<Self> {
616 let [first_byte, second_byte, data @ ..] = data.raw_data();
617
618 const PREFIX_BITS: u8 = 0b1000_0000;
621 const PREFIX_MASK: u8 = 0b1110_0000;
622
623 const R: u8 = 3;
624 const SHIFT: u8 = 8 - R;
625 const REV_SHIFT: u8 = 120 + R;
626
627 if unlikely((first_byte ^ PREFIX_BITS) & PREFIX_MASK != 0) {
628 return None;
629 }
630
631 let mut result = Self {
632 anycast: None,
633 workchain: ((first_byte << R) | (second_byte >> SHIFT)) as i8,
635 address: HashBytes::ZERO,
636 };
637
638 let [mut hi, mut lo]: [u128; 2] =
640 unsafe { std::mem::transmute::<[u8; 32], _>(data[..32].try_into().unwrap()) };
641
642 #[cfg(target_endian = "little")]
644 {
645 hi = hi.swap_bytes();
646 lo = lo.swap_bytes();
647 }
648
649 result.address = unsafe {
651 std::mem::transmute::<[[u8; 16]; 2], HashBytes>([
652 ((hi >> SHIFT) | ((*second_byte as u128) << REV_SHIFT)).to_be_bytes(),
653 ((lo >> SHIFT) | (hi << REV_SHIFT)).to_be_bytes(),
654 ])
655 };
656
657 Some(result)
658 }
659}
660
661#[cfg(feature = "serde")]
662impl serde::Serialize for StdAddr {
663 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
664 where
665 S: serde::Serializer,
666 {
667 if serializer.is_human_readable() {
668 serializer.collect_str(self)
669 } else {
670 (self.workchain, &self.address).serialize(serializer)
671 }
672 }
673}
674
675#[cfg(feature = "serde")]
676impl<'de> serde::Deserialize<'de> for StdAddr {
677 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
678 where
679 D: serde::Deserializer<'de>,
680 {
681 use serde::de::{Error, Visitor};
682
683 struct StdAddrVisitor;
684
685 impl Visitor<'_> for StdAddrVisitor {
686 type Value = StdAddr;
687
688 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
689 f.write_str("a standard address")
690 }
691
692 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
693 where
694 E: Error,
695 {
696 StdAddr::from_str(v).map_err(E::custom)
697 }
698 }
699
700 if deserializer.is_human_readable() {
701 deserializer.deserialize_str(StdAddrVisitor)
702 } else {
703 <(i8, HashBytes)>::deserialize(deserializer)
704 .map(|(workchain, address)| Self::new(workchain, address))
705 }
706 }
707}
708
709#[cfg(feature = "arbitrary")]
710impl<'a> arbitrary::Arbitrary<'a> for StdAddr {
711 #[inline]
712 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
713 Ok(Self {
714 anycast: u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?,
715 workchain: u.arbitrary()?,
716 address: u.arbitrary()?,
717 })
718 }
719
720 #[inline]
721 fn size_hint(depth: usize) -> (usize, Option<usize>) {
722 arbitrary::size_hint::and(Option::<Anycast>::size_hint(depth), (33, Some(33)))
723 }
724}
725
726#[cfg(feature = "base64")]
728pub struct StdAddrBase64Repr<const URL_SAFE: bool = true>;
729
730#[cfg(all(feature = "base64", feature = "serde"))]
731impl<const URL_SAFE: bool> StdAddrBase64Repr<URL_SAFE> {
732 pub fn serialize<S>(addr: &StdAddr, serializer: S) -> Result<S::Ok, S::Error>
734 where
735 S: serde::Serializer,
736 {
737 serializer.collect_str(&DisplayBase64StdAddr {
738 addr,
739 flags: Base64StdAddrFlags {
740 testnet: false,
741 base64_url: URL_SAFE,
742 bounceable: false,
743 },
744 })
745 }
746
747 pub fn deserialize<'de, D>(deserializer: D) -> Result<StdAddr, D::Error>
749 where
750 D: serde::Deserializer<'de>,
751 {
752 use serde::de::{Error, Visitor};
753
754 struct StdAddrBase64Visitor;
755
756 impl Visitor<'_> for StdAddrBase64Visitor {
757 type Value = StdAddr;
758
759 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
760 f.write_str("a standard address")
761 }
762
763 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
764 where
765 E: Error,
766 {
767 StdAddr::from_str_ext(v, StdAddrFormat::any())
768 .map(|(addr, _)| addr)
769 .map_err(E::custom)
770 }
771 }
772
773 deserializer.deserialize_str(StdAddrBase64Visitor)
774 }
775}
776
777#[cfg(feature = "base64")]
779#[derive(Debug, Clone, Copy)]
780pub struct StdAddrFormat {
781 pub allow_raw: bool,
783 pub allow_base64: bool,
785 pub allow_base64_url: bool,
787}
788
789#[cfg(feature = "base64")]
790impl StdAddrFormat {
791 pub const fn any() -> Self {
793 StdAddrFormat {
794 allow_raw: true,
795 allow_base64: true,
796 allow_base64_url: true,
797 }
798 }
799}
800
801#[cfg(feature = "base64")]
803#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
804pub struct Base64StdAddrFlags {
805 pub testnet: bool,
807 pub base64_url: bool,
809 pub bounceable: bool,
811}
812
813#[cfg(feature = "base64")]
815pub struct DisplayBase64StdAddr<'a> {
816 pub addr: &'a StdAddr,
818 pub flags: Base64StdAddrFlags,
820}
821
822#[cfg(feature = "base64")]
823impl std::fmt::Display for DisplayBase64StdAddr<'_> {
824 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
825 use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE, Engine as _};
826
827 let mut buffer = [0u8; 36];
828 buffer[0] = (0x51 - (self.flags.bounceable as i32) * 0x40
829 + (self.flags.testnet as i32) * 0x80) as u8;
830 buffer[1] = self.addr.workchain as u8;
831 buffer[2..34].copy_from_slice(self.addr.address.as_array());
832
833 let crc = crate::crc::crc_16(&buffer[..34]);
834 buffer[34] = (crc >> 8) as u8;
835 buffer[35] = (crc & 0xff) as u8;
836
837 let mut output = [0u8; 48];
838 if self.flags.base64_url {
839 BASE64_URL_SAFE
840 } else {
841 BASE64_STANDARD
842 }
843 .encode_slice(buffer, &mut output)
844 .unwrap();
845
846 let output = unsafe { std::str::from_utf8_unchecked(&output) };
848 f.write_str(output)
849 }
850}
851
852#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
854pub struct VarAddr {
855 pub anycast: Option<Box<Anycast>>,
857 pub address_len: Uint9,
859 pub workchain: i32,
861 pub address: Vec<u8>,
863}
864
865impl VarAddr {
866 pub const BITS_MAX: u16 =
874 2 + 1 + Anycast::BITS_MAX + Uint9::BITS + 32 + Uint9::MAX.into_inner();
875
876 #[inline]
880 pub const fn is_masterchain(&self) -> bool {
881 self.workchain == ShardIdent::MASTERCHAIN.workchain()
882 }
883
884 pub const fn bit_len(&self) -> u16 {
886 let mut bit_len = 2 + 1 + Uint9::BITS + 32 + self.address_len.into_inner();
887 if let Some(anycast) = &self.anycast {
888 bit_len += anycast.bit_len();
889 }
890 bit_len
891 }
892
893 pub fn prefix(&self) -> u64 {
895 let mut prefix = [0; 8];
896 let total_bytes = std::cmp::min(self.address.len(), 8);
897 prefix[..total_bytes].copy_from_slice(&self.address[..total_bytes]);
898 u64::from_be_bytes(prefix)
899 }
900}
901
902impl From<VarAddr> for IntAddr {
903 #[inline]
904 fn from(value: VarAddr) -> Self {
905 Self::Var(value)
906 }
907}
908
909impl Store for VarAddr {
910 fn store_into(
911 &self,
912 builder: &mut CellBuilder,
913 context: &dyn CellContext,
914 ) -> Result<(), Error> {
915 if !builder.has_capacity(self.bit_len(), 0) {
916 return Err(Error::CellOverflow);
917 }
918 ok!(builder.store_small_uint(0b11, 2));
919 ok!(self.anycast.store_into(builder, context));
920 ok!(self.address_len.store_into(builder, context));
921 ok!(builder.store_u32(self.workchain as u32));
922 builder.store_raw(&self.address, self.address_len.into_inner())
923 }
924}
925
926impl Addr for VarAddr {
927 #[inline]
928 fn workchain(&self) -> i32 {
929 self.workchain
930 }
931
932 #[inline]
933 fn prefix(&self) -> u64 {
934 VarAddr::prefix(self)
935 }
936}
937
938#[cfg(feature = "arbitrary")]
939impl<'a> arbitrary::Arbitrary<'a> for VarAddr {
940 #[inline]
941 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
942 let anycast = u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?;
943 let address_len = u.arbitrary::<Uint9>()?;
944 let workchain = u.arbitrary()?;
945
946 let bit_len = address_len.into_inner() as usize;
947 let mut address = u.bytes(bit_len.div_ceil(8))?.to_vec();
948 if let Some(last_byte) = address.last_mut() {
949 let rem = bit_len % 8;
950 if rem != 0 {
951 *last_byte &= u8::MAX << (8 - rem);
952 }
953 }
954
955 Ok(Self {
956 anycast,
957 address_len,
958 workchain,
959 address,
960 })
961 }
962
963 #[inline]
964 fn size_hint(_: usize) -> (usize, Option<usize>) {
965 (1 + 2 + 4, None)
966 }
967}
968
969#[derive(Debug, Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
976pub struct ExtAddr {
977 pub data_bit_len: Uint9,
979 pub data: Vec<u8>,
981}
982
983impl ExtAddr {
984 pub fn new<T>(data_bit_len: u16, data: T) -> Option<Self>
986 where
987 T: Into<Vec<u8>>,
988 {
989 let data_bit_len = Uint9::new(data_bit_len);
990 if data_bit_len.is_valid() {
991 Some(Self {
992 data_bit_len,
993 data: data.into(),
994 })
995 } else {
996 None
997 }
998 }
999
1000 pub const fn bit_len(&self) -> u16 {
1002 Uint9::BITS + self.data_bit_len.into_inner()
1003 }
1004}
1005
1006impl std::fmt::Display for ExtAddr {
1007 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1008 let bitstring = Bitstring {
1009 bytes: &self.data,
1010 bit_len: self.data_bit_len.into_inner(),
1011 };
1012 write!(f, ":{bitstring}")
1013 }
1014}
1015
1016impl FromStr for ExtAddr {
1017 type Err = ParseAddrError;
1018
1019 fn from_str(s: &str) -> Result<Self, Self::Err> {
1020 if s.is_empty() {
1021 return Err(ParseAddrError::Empty);
1022 }
1023
1024 let Some(s) = s.strip_prefix(':') else {
1025 return Err(ParseAddrError::UnexpectedPart);
1026 };
1027
1028 let Ok((data, bit_len)) = Bitstring::from_hex_str(s) else {
1029 return Err(ParseAddrError::InvalidAccountId);
1030 };
1031
1032 ExtAddr::new(bit_len, data).ok_or(ParseAddrError::UnexpectedPart)
1033 }
1034}
1035
1036#[cfg(feature = "serde")]
1037impl serde::Serialize for ExtAddr {
1038 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1039 if serializer.is_human_readable() {
1040 serializer.collect_str(self)
1041 } else {
1042 (self.data_bit_len.into_inner(), &self.data).serialize(serializer)
1043 }
1044 }
1045}
1046
1047#[cfg(feature = "serde")]
1048impl<'de> serde::Deserialize<'de> for ExtAddr {
1049 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1050 use serde::de::{Error, Visitor};
1051
1052 struct ExtAddrVisitor;
1053
1054 impl Visitor<'_> for ExtAddrVisitor {
1055 type Value = ExtAddr;
1056
1057 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1058 f.write_str("an external address")
1059 }
1060
1061 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
1062 ExtAddr::from_str(v).map_err(E::custom)
1063 }
1064 }
1065
1066 if deserializer.is_human_readable() {
1067 deserializer.deserialize_str(ExtAddrVisitor)
1068 } else {
1069 <(u16, Vec<u8>)>::deserialize(deserializer).and_then(|(data_bit_len, data)| {
1070 ExtAddr::new(data_bit_len, data)
1071 .ok_or_else(|| Error::custom("invalid external address data length"))
1072 })
1073 }
1074 }
1075}
1076
1077#[cfg(feature = "arbitrary")]
1078impl<'a> arbitrary::Arbitrary<'a> for ExtAddr {
1079 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1080 let data_bit_len = u.arbitrary::<Uint9>()?;
1081
1082 let bit_len = data_bit_len.into_inner() as usize;
1083 let mut data = u.bytes(bit_len.div_ceil(8))?.to_vec();
1084 if let Some(last_byte) = data.last_mut() {
1085 let rem = bit_len % 8;
1086 if rem != 0 {
1087 *last_byte &= u8::MAX << (8 - rem);
1088 }
1089 }
1090
1091 Ok(Self { data_bit_len, data })
1092 }
1093
1094 #[inline]
1095 fn size_hint(_: usize) -> (usize, Option<usize>) {
1096 (2, None)
1097 }
1098}
1099
1100#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
1106pub struct Anycast {
1107 pub depth: SplitDepth,
1109 pub rewrite_prefix: Vec<u8>,
1111}
1112
1113impl Anycast {
1114 pub const MIN_DEPTH: u8 = 1;
1116 pub const MAX_DEPTH: u8 = 30;
1118
1119 pub const BITS_MAX: u16 = SplitDepth::BITS + Self::MAX_DEPTH as u16;
1121
1122 pub fn from_slice(rewrite_prefix: &CellSlice<'_>) -> Result<Self, Error> {
1124 let depth = ok!(SplitDepth::from_bit_len(rewrite_prefix.size_bits()));
1125
1126 let mut data = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1127 ok!(rewrite_prefix.get_raw(0, &mut data, depth.into_bit_len()));
1128
1129 Ok(Self {
1130 depth,
1131 rewrite_prefix: data,
1132 })
1133 }
1134
1135 pub const fn bit_len(&self) -> u16 {
1137 SplitDepth::BITS + self.depth.into_bit_len()
1138 }
1139}
1140
1141impl std::fmt::Display for Anycast {
1142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1143 let bitstring = Bitstring {
1144 bytes: &self.rewrite_prefix,
1145 bit_len: self.depth.into_bit_len(),
1146 };
1147 std::fmt::Display::fmt(&bitstring, f)
1148 }
1149}
1150
1151impl Store for Anycast {
1152 fn store_into(
1153 &self,
1154 builder: &mut CellBuilder,
1155 context: &dyn CellContext,
1156 ) -> Result<(), Error> {
1157 if !builder.has_capacity(self.bit_len(), 0) {
1158 return Err(Error::CellOverflow);
1159 }
1160 ok!(self.depth.store_into(builder, context));
1161 builder.store_raw(&self.rewrite_prefix, self.depth.into_bit_len())
1162 }
1163}
1164
1165impl<'a> Load<'a> for Anycast {
1166 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1167 let depth = ok!(SplitDepth::load_from(slice));
1168 if !slice.has_remaining(depth.into_bit_len(), 0) {
1169 return Err(Error::CellUnderflow);
1170 }
1171
1172 let mut rewrite_prefix = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1173 ok!(slice.load_raw(&mut rewrite_prefix, depth.into_bit_len()));
1174
1175 Ok(Self {
1176 depth,
1177 rewrite_prefix,
1178 })
1179 }
1180}
1181
1182#[cfg(feature = "arbitrary")]
1183impl<'a> arbitrary::Arbitrary<'a> for Anycast {
1184 #[inline]
1185 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1186 let split_depth = SplitDepth::arbitrary(u)?;
1187 let bit_len = split_depth.into_bit_len();
1188
1189 let bytes = u.bytes(bit_len.div_ceil(8) as _)?;
1190
1191 let b = CellBuilder::from_raw_data(bytes, bit_len).unwrap();
1192 Ok(Self::from_slice(&b.as_data_slice()).unwrap())
1193 }
1194
1195 #[inline]
1196 fn size_hint(_: usize) -> (usize, Option<usize>) {
1197 (2, Some(5))
1198 }
1199}
1200
1201#[cfg(test)]
1202mod tests {
1203 use super::*;
1204 use crate::dict::Dict;
1205
1206 #[test]
1207 fn dict_with_std_addr_keys() {
1208 let mut dict = Dict::<StdAddr, u32>::new();
1209 dict.set(StdAddr::new(-1, HashBytes([0x33; 32])), 123)
1210 .unwrap();
1211 dict.set(StdAddr::new(0, HashBytes([0x10; 32])), 321)
1212 .unwrap();
1213 dict.set(StdAddr::new(-1, HashBytes([0x55; 32])), 234)
1214 .unwrap();
1215 dict.set(StdAddr::new(0, HashBytes([0x20; 32])), 432)
1216 .unwrap();
1217
1218 for entry in dict.iter() {
1219 let (addr, value) = entry.unwrap();
1220 println!("{addr}: {value}");
1221 }
1222 }
1223
1224 #[test]
1225 fn anycast_str() {
1226 let empty_res = Anycast::from_slice(&Cell::empty_cell().as_slice().unwrap());
1228 assert_eq!(empty_res.unwrap_err(), Error::IntOverflow);
1229
1230 let mut prefix = CellBuilder::new();
1232 prefix.store_bit_one().unwrap();
1233 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1234 assert_eq!(anycast.to_string(), "c_");
1235
1236 let mut prefix = CellBuilder::new();
1238 prefix.store_u8(0xa5).unwrap();
1239 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1240 assert_eq!(anycast.to_string(), "a5");
1241
1242 let mut prefix = CellBuilder::new();
1244 prefix.store_uint(0xb00b1e5, 28).unwrap();
1245 prefix.store_zeros(2).unwrap();
1246 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1247 assert_eq!(anycast.to_string(), "b00b1e52_");
1248 }
1249
1250 #[test]
1251 fn address_prefix() {
1252 let addr = "0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415"
1253 .parse::<StdAddr>()
1254 .unwrap();
1255 assert_eq!(addr.prefix(), 0xece57bcc6c530283);
1256
1257 let var_addr = VarAddr {
1258 anycast: None,
1259 address_len: Uint9::new(32),
1260 workchain: 0,
1261 address: vec![0xb0, 0xba, 0xca, 0xfe],
1262 };
1263 assert_eq!(var_addr.prefix(), 0xb0bacafe00000000);
1264
1265 let var_addr = VarAddr {
1266 anycast: None,
1267 address_len: Uint9::new(72),
1268 workchain: 0,
1269 address: vec![0xb0, 0xba, 0xca, 0xfe, 0xb0, 0x0b, 0x1e, 0x5a, 0xff],
1270 };
1271 assert_eq!(var_addr.prefix(), 0xb0bacafeb00b1e5a);
1272 }
1273
1274 #[test]
1275 fn base64_address() {
1276 let addr = "0:84545d4d2cada0ce811705d534c298ca42d29315d03a16eee794cefd191dfa79"
1277 .parse::<StdAddr>()
1278 .unwrap();
1279 assert_eq!(
1280 addr.display_base64(true).to_string(),
1281 "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw"
1282 );
1283 assert_eq!(
1284 StdAddr::from_str_ext(
1285 "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw",
1286 StdAddrFormat::any()
1287 )
1288 .unwrap(),
1289 (addr, Base64StdAddrFlags {
1290 testnet: false,
1291 base64_url: false,
1292 bounceable: true,
1293 })
1294 );
1295
1296 let addr = "0:dddde93b1d3398f0b4305c08de9a032e0bc1b257c4ce2c72090aea1ff3e9ecfd"
1297 .parse::<StdAddr>()
1298 .unwrap();
1299 assert_eq!(
1300 addr.display_base64_url(false).to_string(),
1301 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_Tyv"
1302 );
1303 assert_eq!(
1304 addr.display_base64(false).to_string(),
1305 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv"
1306 );
1307
1308 assert_eq!(
1309 StdAddr::from_str_ext(
1310 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv",
1311 StdAddrFormat::any()
1312 )
1313 .unwrap(),
1314 (addr.clone(), Base64StdAddrFlags {
1315 testnet: false,
1316 base64_url: false,
1317 bounceable: false,
1318 })
1319 );
1320
1321 assert_eq!(
1322 addr.display_base64_url(true).to_string(),
1323 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq"
1324 );
1325 assert_eq!(
1326 addr.display_base64(true).to_string(),
1327 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/WFq"
1328 );
1329
1330 assert_eq!(
1331 StdAddr::from_str_ext(
1332 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq",
1333 StdAddrFormat::any()
1334 )
1335 .unwrap(),
1336 (addr, Base64StdAddrFlags {
1337 testnet: false,
1338 base64_url: true,
1339 bounceable: true,
1340 })
1341 );
1342 }
1343}