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 pub const fn new_masterchain(address: HashBytes) -> Self {
374 Self {
375 anycast: None,
376 workchain: ShardIdent::MASTERCHAIN.workchain() as i8,
377 address,
378 }
379 }
380
381 #[inline]
383 pub const fn new(workchain: i8, address: HashBytes) -> Self {
384 Self {
385 anycast: None,
386 workchain,
387 address,
388 }
389 }
390
391 #[cfg(feature = "base64")]
393 pub fn from_str_ext(
394 s: &str,
395 format: StdAddrFormat,
396 ) -> Result<(Self, Base64StdAddrFlags), ParseAddrError> {
397 use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE, Engine as _};
398
399 match s.len() {
400 0 => Err(ParseAddrError::Empty),
401 66..=69 if format.allow_raw => Self::from_str(s).map(|addr| (addr, Default::default())),
402 48 if format.allow_base64 || format.allow_base64_url => {
403 let mut buffer = [0u8; 36];
404
405 let base64_url = s.contains(['_', '-']);
406
407 let Ok(36) = if base64_url {
408 BASE64_URL_SAFE
409 } else {
410 BASE64_STANDARD
411 }
412 .decode_slice(s, &mut buffer) else {
413 return Err(ParseAddrError::BadFormat);
414 };
415
416 #[cfg(not(fuzzing))]
417 {
418 let crc = crate::crc::crc_16(&buffer[..34]);
419 if buffer[34] as u16 != (crc >> 8) || buffer[35] as u16 != (crc & 0xff) {
420 return Err(ParseAddrError::BadFormat);
421 }
422 }
423
424 let addr = StdAddr::new(
425 buffer[1] as i8,
426 HashBytes(buffer[2..34].try_into().unwrap()),
427 );
428 let flags = Base64StdAddrFlags {
429 testnet: buffer[0] & 0x80 != 0,
430 base64_url,
431 bounceable: buffer[0] & 0x40 == 0,
432 };
433 Ok((addr, flags))
434 }
435 _ => Err(ParseAddrError::BadFormat),
436 }
437 }
438
439 #[inline]
443 pub const fn is_masterchain(&self) -> bool {
444 self.workchain as i32 == ShardIdent::MASTERCHAIN.workchain()
445 }
446
447 pub const fn is_zero(&self) -> bool {
449 self.workchain == 0 && self.anycast.is_none() && self.address.is_zero()
450 }
451
452 pub const fn bit_len(&self) -> u16 {
454 let mut bit_len = Self::BITS_WITHOUT_ANYCAST;
455 if let Some(anycast) = &self.anycast {
456 bit_len += anycast.bit_len();
457 }
458 bit_len
459 }
460
461 pub const fn prefix(&self) -> u64 {
463 u64::from_be_bytes(*self.address.first_chunk())
464 }
465
466 #[cfg(feature = "base64")]
468 pub const fn display_base64(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
469 DisplayBase64StdAddr {
470 addr: self,
471 flags: Base64StdAddrFlags {
472 testnet: false,
473 base64_url: false,
474 bounceable,
475 },
476 }
477 }
478
479 #[cfg(feature = "base64")]
481 pub const fn display_base64_url(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
482 DisplayBase64StdAddr {
483 addr: self,
484 flags: Base64StdAddrFlags {
485 testnet: false,
486 base64_url: true,
487 bounceable,
488 },
489 }
490 }
491}
492
493impl Default for StdAddr {
494 #[inline]
495 fn default() -> Self {
496 Self::ZERO
497 }
498}
499
500impl Addr for StdAddr {
501 #[inline]
502 fn workchain(&self) -> i32 {
503 self.workchain as i32
504 }
505
506 #[inline]
507 fn prefix(&self) -> u64 {
508 StdAddr::prefix(self)
509 }
510}
511
512impl std::fmt::Display for StdAddr {
513 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
514 if let Some(anycast) = &self.anycast {
515 ok!(f.write_fmt(format_args!("{anycast}:")))
516 }
517
518 f.write_fmt(format_args!("{}:{}", self.workchain, self.address))
519 }
520}
521
522impl From<(i8, HashBytes)> for StdAddr {
523 #[inline]
524 fn from((workchain, address): (i8, HashBytes)) -> Self {
525 Self::new(workchain, address)
526 }
527}
528
529impl From<(i8, [u8; 32])> for StdAddr {
530 #[inline]
531 fn from((workchain, address): (i8, [u8; 32])) -> Self {
532 Self::new(workchain, HashBytes(address))
533 }
534}
535
536impl From<StdAddr> for IntAddr {
537 #[inline]
538 fn from(value: StdAddr) -> Self {
539 Self::Std(value)
540 }
541}
542
543impl FromStr for StdAddr {
544 type Err = ParseAddrError;
545
546 fn from_str(s: &str) -> Result<Self, Self::Err> {
547 if s.is_empty() {
548 return Err(ParseAddrError::Empty);
549 }
550
551 let mut result = Self::default();
552
553 let mut parts = s.split(':');
554 match parts.next() {
555 Some(part) => match part.parse() {
556 Ok(workchain) => result.workchain = workchain,
557 Err(_) => return Err(ParseAddrError::InvalidWorkchain),
558 },
559 None => return Err(ParseAddrError::Empty),
560 }
561
562 match parts.next() {
563 Some(part) => match hex::decode_to_slice(part, &mut result.address.0) {
564 Ok(()) => {}
565 Err(_) => return Err(ParseAddrError::InvalidAccountId),
566 },
567 None => return Err(ParseAddrError::InvalidAccountId),
568 }
569
570 if parts.next().is_none() {
571 Ok(result)
572 } else {
573 Err(ParseAddrError::UnexpectedPart)
574 }
575 }
576}
577
578impl Store for StdAddr {
579 fn store_into(
580 &self,
581 builder: &mut CellBuilder,
582 context: &dyn CellContext,
583 ) -> Result<(), Error> {
584 if !builder.has_capacity(self.bit_len(), 0) {
585 return Err(Error::CellOverflow);
586 }
587 ok!(builder.store_small_uint(0b10, 2));
588 ok!(self.anycast.store_into(builder, context));
589 ok!(builder.store_u8(self.workchain as u8));
590 builder.store_u256(&self.address)
591 }
592}
593
594impl<'a> Load<'a> for StdAddr {
595 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
596 if !ok!(slice.load_bit()) || ok!(slice.load_bit()) {
597 return Err(Error::InvalidTag);
598 }
599
600 Ok(Self {
601 anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
602 workchain: ok!(slice.load_u8()) as i8,
603 address: ok!(slice.load_u256()),
604 })
605 }
606}
607
608impl crate::dict::DictKey for StdAddr {
609 const BITS: u16 = StdAddr::BITS_WITHOUT_ANYCAST;
610}
611
612impl crate::dict::StoreDictKey for StdAddr {
613 fn store_into_data(&self, builder: &mut CellDataBuilder) -> Result<(), Error> {
614 if self.anycast.is_some() || !builder.has_capacity_bits(Self::BITS_WITHOUT_ANYCAST) {
615 return Err(Error::InvalidData);
616 }
617 ok!(builder.store_small_uint(0b100, 3)); ok!(builder.store_u8(self.workchain as u8));
619 builder.store_u256(&self.address)
620 }
621}
622
623impl crate::dict::LoadDictKey for StdAddr {
624 fn load_from_data(data: &CellDataBuilder) -> Option<Self> {
625 let [first_byte, second_byte, data @ ..] = data.raw_data();
626
627 const PREFIX_BITS: u8 = 0b1000_0000;
630 const PREFIX_MASK: u8 = 0b1110_0000;
631
632 const R: u8 = 3;
633 const SHIFT: u8 = 8 - R;
634 const REV_SHIFT: u8 = 120 + R;
635
636 if unlikely((first_byte ^ PREFIX_BITS) & PREFIX_MASK != 0) {
637 return None;
638 }
639
640 let mut result = Self {
641 anycast: None,
642 workchain: ((first_byte << R) | (second_byte >> SHIFT)) as i8,
644 address: HashBytes::ZERO,
645 };
646
647 let [mut hi, mut lo]: [u128; 2] =
649 unsafe { std::mem::transmute::<[u8; 32], _>(data[..32].try_into().unwrap()) };
650
651 #[cfg(target_endian = "little")]
653 {
654 hi = hi.swap_bytes();
655 lo = lo.swap_bytes();
656 }
657
658 result.address = unsafe {
660 std::mem::transmute::<[[u8; 16]; 2], HashBytes>([
661 ((hi >> SHIFT) | ((*second_byte as u128) << REV_SHIFT)).to_be_bytes(),
662 ((lo >> SHIFT) | (hi << REV_SHIFT)).to_be_bytes(),
663 ])
664 };
665
666 Some(result)
667 }
668}
669
670#[cfg(feature = "serde")]
671impl serde::Serialize for StdAddr {
672 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
673 where
674 S: serde::Serializer,
675 {
676 if serializer.is_human_readable() {
677 serializer.collect_str(self)
678 } else {
679 (self.workchain, &self.address).serialize(serializer)
680 }
681 }
682}
683
684#[cfg(feature = "serde")]
685impl<'de> serde::Deserialize<'de> for StdAddr {
686 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
687 where
688 D: serde::Deserializer<'de>,
689 {
690 use serde::de::{Error, Visitor};
691
692 struct StdAddrVisitor;
693
694 impl Visitor<'_> for StdAddrVisitor {
695 type Value = StdAddr;
696
697 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
698 f.write_str("a standard address")
699 }
700
701 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
702 where
703 E: Error,
704 {
705 StdAddr::from_str(v).map_err(E::custom)
706 }
707 }
708
709 if deserializer.is_human_readable() {
710 deserializer.deserialize_str(StdAddrVisitor)
711 } else {
712 <(i8, HashBytes)>::deserialize(deserializer)
713 .map(|(workchain, address)| Self::new(workchain, address))
714 }
715 }
716}
717
718#[cfg(feature = "arbitrary")]
719impl<'a> arbitrary::Arbitrary<'a> for StdAddr {
720 #[inline]
721 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
722 Ok(Self {
723 anycast: u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?,
724 workchain: u.arbitrary()?,
725 address: u.arbitrary()?,
726 })
727 }
728
729 #[inline]
730 fn size_hint(depth: usize) -> (usize, Option<usize>) {
731 arbitrary::size_hint::and(Option::<Anycast>::size_hint(depth), (33, Some(33)))
732 }
733}
734
735#[cfg(feature = "base64")]
737pub struct StdAddrBase64Repr<const URL_SAFE: bool = true>;
738
739#[cfg(all(feature = "base64", feature = "serde"))]
740impl<const URL_SAFE: bool> StdAddrBase64Repr<URL_SAFE> {
741 pub fn serialize<S>(addr: &StdAddr, serializer: S) -> Result<S::Ok, S::Error>
743 where
744 S: serde::Serializer,
745 {
746 serializer.collect_str(&DisplayBase64StdAddr {
747 addr,
748 flags: Base64StdAddrFlags {
749 testnet: false,
750 base64_url: URL_SAFE,
751 bounceable: false,
752 },
753 })
754 }
755
756 pub fn deserialize<'de, D>(deserializer: D) -> Result<StdAddr, D::Error>
758 where
759 D: serde::Deserializer<'de>,
760 {
761 use serde::de::{Error, Visitor};
762
763 struct StdAddrBase64Visitor;
764
765 impl Visitor<'_> for StdAddrBase64Visitor {
766 type Value = StdAddr;
767
768 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
769 f.write_str("a standard address")
770 }
771
772 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
773 where
774 E: Error,
775 {
776 StdAddr::from_str_ext(v, StdAddrFormat::any())
777 .map(|(addr, _)| addr)
778 .map_err(E::custom)
779 }
780 }
781
782 deserializer.deserialize_str(StdAddrBase64Visitor)
783 }
784}
785
786#[cfg(feature = "base64")]
788#[derive(Debug, Clone, Copy)]
789pub struct StdAddrFormat {
790 pub allow_raw: bool,
792 pub allow_base64: bool,
794 pub allow_base64_url: bool,
796}
797
798#[cfg(feature = "base64")]
799impl StdAddrFormat {
800 pub const fn any() -> Self {
802 StdAddrFormat {
803 allow_raw: true,
804 allow_base64: true,
805 allow_base64_url: true,
806 }
807 }
808}
809
810#[cfg(feature = "base64")]
812#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
813pub struct Base64StdAddrFlags {
814 pub testnet: bool,
816 pub base64_url: bool,
818 pub bounceable: bool,
820}
821
822#[cfg(feature = "base64")]
824pub struct DisplayBase64StdAddr<'a> {
825 pub addr: &'a StdAddr,
827 pub flags: Base64StdAddrFlags,
829}
830
831#[cfg(feature = "base64")]
832impl std::fmt::Display for DisplayBase64StdAddr<'_> {
833 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
834 use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE, Engine as _};
835
836 let mut buffer = [0u8; 36];
837 buffer[0] = (0x51 - (self.flags.bounceable as i32) * 0x40
838 + (self.flags.testnet as i32) * 0x80) as u8;
839 buffer[1] = self.addr.workchain as u8;
840 buffer[2..34].copy_from_slice(self.addr.address.as_array());
841
842 let crc = crate::crc::crc_16(&buffer[..34]);
843 buffer[34] = (crc >> 8) as u8;
844 buffer[35] = (crc & 0xff) as u8;
845
846 let mut output = [0u8; 48];
847 if self.flags.base64_url {
848 BASE64_URL_SAFE
849 } else {
850 BASE64_STANDARD
851 }
852 .encode_slice(buffer, &mut output)
853 .unwrap();
854
855 let output = unsafe { std::str::from_utf8_unchecked(&output) };
857 f.write_str(output)
858 }
859}
860
861#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
863pub struct VarAddr {
864 pub anycast: Option<Box<Anycast>>,
866 pub address_len: Uint9,
868 pub workchain: i32,
870 pub address: Vec<u8>,
872}
873
874impl VarAddr {
875 pub const BITS_MAX: u16 =
883 2 + 1 + Anycast::BITS_MAX + Uint9::BITS + 32 + Uint9::MAX.into_inner();
884
885 #[inline]
889 pub const fn is_masterchain(&self) -> bool {
890 self.workchain == ShardIdent::MASTERCHAIN.workchain()
891 }
892
893 pub const fn bit_len(&self) -> u16 {
895 let mut bit_len = 2 + 1 + Uint9::BITS + 32 + self.address_len.into_inner();
896 if let Some(anycast) = &self.anycast {
897 bit_len += anycast.bit_len();
898 }
899 bit_len
900 }
901
902 pub fn prefix(&self) -> u64 {
904 let mut prefix = [0; 8];
905 let total_bytes = std::cmp::min(self.address.len(), 8);
906 prefix[..total_bytes].copy_from_slice(&self.address[..total_bytes]);
907 u64::from_be_bytes(prefix)
908 }
909}
910
911impl From<VarAddr> for IntAddr {
912 #[inline]
913 fn from(value: VarAddr) -> Self {
914 Self::Var(value)
915 }
916}
917
918impl Store for VarAddr {
919 fn store_into(
920 &self,
921 builder: &mut CellBuilder,
922 context: &dyn CellContext,
923 ) -> Result<(), Error> {
924 if !builder.has_capacity(self.bit_len(), 0) {
925 return Err(Error::CellOverflow);
926 }
927 ok!(builder.store_small_uint(0b11, 2));
928 ok!(self.anycast.store_into(builder, context));
929 ok!(self.address_len.store_into(builder, context));
930 ok!(builder.store_u32(self.workchain as u32));
931 builder.store_raw(&self.address, self.address_len.into_inner())
932 }
933}
934
935impl Addr for VarAddr {
936 #[inline]
937 fn workchain(&self) -> i32 {
938 self.workchain
939 }
940
941 #[inline]
942 fn prefix(&self) -> u64 {
943 VarAddr::prefix(self)
944 }
945}
946
947#[cfg(feature = "arbitrary")]
948impl<'a> arbitrary::Arbitrary<'a> for VarAddr {
949 #[inline]
950 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
951 let anycast = u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?;
952 let address_len = u.arbitrary::<Uint9>()?;
953 let workchain = u.arbitrary()?;
954
955 let bit_len = address_len.into_inner() as usize;
956 let mut address = u.bytes(bit_len.div_ceil(8))?.to_vec();
957 if let Some(last_byte) = address.last_mut() {
958 let rem = bit_len % 8;
959 if rem != 0 {
960 *last_byte &= u8::MAX << (8 - rem);
961 }
962 }
963
964 Ok(Self {
965 anycast,
966 address_len,
967 workchain,
968 address,
969 })
970 }
971
972 #[inline]
973 fn size_hint(_: usize) -> (usize, Option<usize>) {
974 (1 + 2 + 4, None)
975 }
976}
977
978#[derive(Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
985pub struct ExtAddr {
986 pub data_bit_len: Uint9,
988 pub data: Box<[u8]>,
990}
991
992impl ExtAddr {
993 pub fn new<T>(data_bit_len: u16, data: T) -> Option<Self>
995 where
996 T: Into<Vec<u8>>,
997 {
998 let data_bit_len = Uint9::new(data_bit_len);
999 if data_bit_len.is_valid() {
1000 let mut data = data.into();
1001
1002 let bits = data_bit_len.into_inner() as usize;
1004 let bytes = bits.div_ceil(8);
1005 if let Some(additional) = bytes.checked_sub(data.len())
1006 && additional > 0
1007 {
1008 data.reserve_exact(additional);
1010 }
1011 data.resize(bytes, 0);
1012
1013 let rem = bits % 8;
1015 if rem > 0 {
1016 debug_assert!(bytes > 0, "non-zero bits cannot fit into zero bytes");
1017 let tag_mask = 1u8 << (7 - rem);
1018 let data_mask = !(tag_mask - 1) << 1;
1019 data[bytes - 1] &= data_mask;
1020 }
1021
1022 Some(Self {
1023 data_bit_len,
1024 data: data.into_boxed_slice(),
1025 })
1026 } else {
1027 None
1028 }
1029 }
1030
1031 pub const fn bit_len(&self) -> u16 {
1033 Uint9::BITS + self.data_bit_len.into_inner()
1034 }
1035}
1036
1037impl std::fmt::Display for ExtAddr {
1038 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1039 let bitstring = Bitstring {
1040 bytes: &self.data,
1041 bit_len: self.data_bit_len.into_inner(),
1042 };
1043 write!(f, ":{bitstring}")
1044 }
1045}
1046
1047impl std::fmt::Debug for ExtAddr {
1048 #[inline]
1049 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1050 std::fmt::Display::fmt(self, f)
1051 }
1052}
1053
1054impl FromStr for ExtAddr {
1055 type Err = ParseAddrError;
1056
1057 fn from_str(s: &str) -> Result<Self, Self::Err> {
1058 if s.is_empty() {
1059 return Err(ParseAddrError::Empty);
1060 }
1061
1062 let Some(s) = s.strip_prefix(':') else {
1063 return Err(ParseAddrError::UnexpectedPart);
1064 };
1065
1066 let Ok((data, bit_len)) = Bitstring::from_hex_str(s) else {
1067 return Err(ParseAddrError::InvalidAccountId);
1068 };
1069
1070 ExtAddr::new(bit_len, data).ok_or(ParseAddrError::UnexpectedPart)
1071 }
1072}
1073
1074#[cfg(feature = "serde")]
1075impl serde::Serialize for ExtAddr {
1076 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1077 if serializer.is_human_readable() {
1078 serializer.collect_str(self)
1079 } else {
1080 (self.data_bit_len.into_inner(), &self.data).serialize(serializer)
1081 }
1082 }
1083}
1084
1085#[cfg(feature = "serde")]
1086impl<'de> serde::Deserialize<'de> for ExtAddr {
1087 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1088 use serde::de::{Error, Visitor};
1089
1090 struct ExtAddrVisitor;
1091
1092 impl Visitor<'_> for ExtAddrVisitor {
1093 type Value = ExtAddr;
1094
1095 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1096 f.write_str("an external address")
1097 }
1098
1099 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
1100 ExtAddr::from_str(v).map_err(E::custom)
1101 }
1102 }
1103
1104 if deserializer.is_human_readable() {
1105 deserializer.deserialize_str(ExtAddrVisitor)
1106 } else {
1107 <(u16, Vec<u8>)>::deserialize(deserializer).and_then(|(data_bit_len, data)| {
1108 ExtAddr::new(data_bit_len, data)
1109 .ok_or_else(|| Error::custom("invalid external address data length"))
1110 })
1111 }
1112 }
1113}
1114
1115#[cfg(feature = "arbitrary")]
1116impl<'a> arbitrary::Arbitrary<'a> for ExtAddr {
1117 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1118 let data_bit_len = u.arbitrary::<Uint9>()?;
1119
1120 let bit_len = data_bit_len.into_inner() as usize;
1121 let mut data = u.bytes(bit_len.div_ceil(8))?.to_vec();
1122 if let Some(last_byte) = data.last_mut() {
1123 let rem = bit_len % 8;
1124 if rem != 0 {
1125 *last_byte &= u8::MAX << (8 - rem);
1126 }
1127 }
1128
1129 Ok(Self {
1130 data_bit_len,
1131 data: data.into_boxed_slice(),
1132 })
1133 }
1134
1135 #[inline]
1136 fn size_hint(_: usize) -> (usize, Option<usize>) {
1137 (2, None)
1138 }
1139}
1140
1141#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
1147pub struct Anycast {
1148 pub depth: SplitDepth,
1150 pub rewrite_prefix: Vec<u8>,
1152}
1153
1154impl Anycast {
1155 pub const MIN_DEPTH: u8 = 1;
1157 pub const MAX_DEPTH: u8 = 30;
1159
1160 pub const BITS_MAX: u16 = SplitDepth::BITS + Self::MAX_DEPTH as u16;
1162
1163 pub fn from_slice(rewrite_prefix: &CellSlice<'_>) -> Result<Self, Error> {
1165 let depth = ok!(SplitDepth::from_bit_len(rewrite_prefix.size_bits()));
1166
1167 let mut data = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1168 ok!(rewrite_prefix.get_raw(0, &mut data, depth.into_bit_len()));
1169
1170 Ok(Self {
1171 depth,
1172 rewrite_prefix: data,
1173 })
1174 }
1175
1176 pub const fn bit_len(&self) -> u16 {
1178 SplitDepth::BITS + self.depth.into_bit_len()
1179 }
1180}
1181
1182impl std::fmt::Display for Anycast {
1183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1184 let bitstring = Bitstring {
1185 bytes: &self.rewrite_prefix,
1186 bit_len: self.depth.into_bit_len(),
1187 };
1188 std::fmt::Display::fmt(&bitstring, f)
1189 }
1190}
1191
1192impl Store for Anycast {
1193 fn store_into(
1194 &self,
1195 builder: &mut CellBuilder,
1196 context: &dyn CellContext,
1197 ) -> Result<(), Error> {
1198 if !builder.has_capacity(self.bit_len(), 0) {
1199 return Err(Error::CellOverflow);
1200 }
1201 ok!(self.depth.store_into(builder, context));
1202 builder.store_raw(&self.rewrite_prefix, self.depth.into_bit_len())
1203 }
1204}
1205
1206impl<'a> Load<'a> for Anycast {
1207 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1208 let depth = ok!(SplitDepth::load_from(slice));
1209 if !slice.has_remaining(depth.into_bit_len(), 0) {
1210 return Err(Error::CellUnderflow);
1211 }
1212
1213 let mut rewrite_prefix = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1214 ok!(slice.load_raw(&mut rewrite_prefix, depth.into_bit_len()));
1215
1216 Ok(Self {
1217 depth,
1218 rewrite_prefix,
1219 })
1220 }
1221}
1222
1223#[cfg(feature = "arbitrary")]
1224impl<'a> arbitrary::Arbitrary<'a> for Anycast {
1225 #[inline]
1226 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1227 let split_depth = SplitDepth::arbitrary(u)?;
1228 let bit_len = split_depth.into_bit_len();
1229
1230 let bytes = u.bytes(bit_len.div_ceil(8) as _)?;
1231
1232 let b = CellBuilder::from_raw_data(bytes, bit_len).unwrap();
1233 Ok(Self::from_slice(&b.as_data_slice()).unwrap())
1234 }
1235
1236 #[inline]
1237 fn size_hint(_: usize) -> (usize, Option<usize>) {
1238 (2, Some(5))
1239 }
1240}
1241
1242#[cfg(test)]
1243mod tests {
1244 use super::*;
1245 use crate::dict::Dict;
1246
1247 #[test]
1248 fn dict_with_std_addr_keys() {
1249 let mut dict = Dict::<StdAddr, u32>::new();
1250 dict.set(StdAddr::new(-1, HashBytes([0x33; 32])), 123)
1251 .unwrap();
1252 dict.set(StdAddr::new(0, HashBytes([0x10; 32])), 321)
1253 .unwrap();
1254 dict.set(StdAddr::new(-1, HashBytes([0x55; 32])), 234)
1255 .unwrap();
1256 dict.set(StdAddr::new(0, HashBytes([0x20; 32])), 432)
1257 .unwrap();
1258
1259 for entry in dict.iter() {
1260 let (addr, value) = entry.unwrap();
1261 println!("{addr}: {value}");
1262 }
1263 }
1264
1265 #[test]
1266 fn anycast_str() {
1267 let empty_res = Anycast::from_slice(&Cell::empty_cell().as_slice().unwrap());
1269 assert_eq!(empty_res.unwrap_err(), Error::IntOverflow);
1270
1271 let mut prefix = CellBuilder::new();
1273 prefix.store_bit_one().unwrap();
1274 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1275 assert_eq!(anycast.to_string(), "c_");
1276
1277 let mut prefix = CellBuilder::new();
1279 prefix.store_u8(0xa5).unwrap();
1280 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1281 assert_eq!(anycast.to_string(), "a5");
1282
1283 let mut prefix = CellBuilder::new();
1285 prefix.store_uint(0xb00b1e5, 28).unwrap();
1286 prefix.store_zeros(2).unwrap();
1287 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1288 assert_eq!(anycast.to_string(), "b00b1e52_");
1289 }
1290
1291 #[test]
1292 fn address_prefix() {
1293 let addr = "0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415"
1294 .parse::<StdAddr>()
1295 .unwrap();
1296 assert_eq!(addr.prefix(), 0xece57bcc6c530283);
1297
1298 let var_addr = VarAddr {
1299 anycast: None,
1300 address_len: Uint9::new(32),
1301 workchain: 0,
1302 address: vec![0xb0, 0xba, 0xca, 0xfe],
1303 };
1304 assert_eq!(var_addr.prefix(), 0xb0bacafe00000000);
1305
1306 let var_addr = VarAddr {
1307 anycast: None,
1308 address_len: Uint9::new(72),
1309 workchain: 0,
1310 address: vec![0xb0, 0xba, 0xca, 0xfe, 0xb0, 0x0b, 0x1e, 0x5a, 0xff],
1311 };
1312 assert_eq!(var_addr.prefix(), 0xb0bacafeb00b1e5a);
1313 }
1314
1315 #[test]
1316 fn base64_address() {
1317 let addr = "0:84545d4d2cada0ce811705d534c298ca42d29315d03a16eee794cefd191dfa79"
1318 .parse::<StdAddr>()
1319 .unwrap();
1320 assert_eq!(
1321 addr.display_base64(true).to_string(),
1322 "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw"
1323 );
1324 assert_eq!(
1325 StdAddr::from_str_ext(
1326 "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw",
1327 StdAddrFormat::any()
1328 )
1329 .unwrap(),
1330 (addr, Base64StdAddrFlags {
1331 testnet: false,
1332 base64_url: false,
1333 bounceable: true,
1334 })
1335 );
1336
1337 let addr = "0:dddde93b1d3398f0b4305c08de9a032e0bc1b257c4ce2c72090aea1ff3e9ecfd"
1338 .parse::<StdAddr>()
1339 .unwrap();
1340 assert_eq!(
1341 addr.display_base64_url(false).to_string(),
1342 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_Tyv"
1343 );
1344 assert_eq!(
1345 addr.display_base64(false).to_string(),
1346 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv"
1347 );
1348
1349 assert_eq!(
1350 StdAddr::from_str_ext(
1351 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv",
1352 StdAddrFormat::any()
1353 )
1354 .unwrap(),
1355 (addr.clone(), Base64StdAddrFlags {
1356 testnet: false,
1357 base64_url: false,
1358 bounceable: false,
1359 })
1360 );
1361
1362 assert_eq!(
1363 addr.display_base64_url(true).to_string(),
1364 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq"
1365 );
1366 assert_eq!(
1367 addr.display_base64(true).to_string(),
1368 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/WFq"
1369 );
1370
1371 assert_eq!(
1372 StdAddr::from_str_ext(
1373 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq",
1374 StdAddrFormat::any()
1375 )
1376 .unwrap(),
1377 (addr, Base64StdAddrFlags {
1378 testnet: false,
1379 base64_url: true,
1380 bounceable: true,
1381 })
1382 );
1383 }
1384
1385 #[test]
1386 fn ext_addr_works() {
1387 for bits in 0..=32 {
1388 let addr = ExtAddr::new(bits, vec![0xaau8; 2]).unwrap();
1389 println!("{addr}");
1390 }
1391 }
1392}