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
9pub trait Addr {
11 fn workchain(&self) -> i32;
13 fn prefix(&self) -> u64;
15}
16
17#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
19pub enum IntAddr {
20 Std(StdAddr),
22 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 pub const BITS_MAX: u16 = 1 + VarAddr::BITS_MAX;
36
37 #[inline]
41 pub const fn is_masterchain(&self) -> bool {
42 self.workchain() == ShardIdent::MASTERCHAIN.workchain()
43 }
44
45 #[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 #[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 #[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 #[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 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 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 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"), }
132 }
133}
134
135impl Store for IntAddr {
136 fn store_into(
137 &self,
138 builder: &mut CellBuilder,
139 context: &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().div_ceil(8) as usize];
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 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 StdAddr::deserialize(deserializer).map(IntAddr::Std)
205 }
206}
207
208#[cfg(feature = "arbitrary")]
209impl<'a> arbitrary::Arbitrary<'a> for IntAddr {
210 #[inline]
211 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
212 if u.ratio(1u8, 20u8)? {
213 u.arbitrary().map(Self::Var)
214 } else {
215 u.arbitrary().map(Self::Std)
216 }
217 }
218
219 #[inline]
220 fn size_hint(depth: usize) -> (usize, Option<usize>) {
221 Self::try_size_hint(depth).unwrap_or_default()
222 }
223
224 #[inline]
225 fn try_size_hint(
226 depth: usize,
227 ) -> Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
228 Ok(arbitrary::size_hint::and(
229 <u8 as arbitrary::Arbitrary>::try_size_hint(depth)?,
230 arbitrary::size_hint::or(StdAddr::size_hint(depth), VarAddr::size_hint(depth)),
231 ))
232 }
233}
234
235#[derive(Debug, Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
237pub struct StdAddr {
238 pub anycast: Option<Box<Anycast>>,
240 pub workchain: i8,
242 pub address: HashBytes,
244}
245
246impl StdAddr {
247 pub const BITS_WITHOUT_ANYCAST: u16 = 2 + 1 + 8 + 256;
254
255 pub const BITS_MAX: u16 = Self::BITS_WITHOUT_ANYCAST + Anycast::BITS_MAX;
257
258 #[inline]
260 pub const fn new(workchain: i8, address: HashBytes) -> Self {
261 Self {
262 anycast: None,
263 workchain,
264 address,
265 }
266 }
267
268 #[cfg(feature = "base64")]
270 pub fn from_str_ext(
271 s: &str,
272 format: StdAddrFormat,
273 ) -> Result<(Self, Base64StdAddrFlags), ParseAddrError> {
274 use base64::prelude::{Engine as _, BASE64_STANDARD, BASE64_URL_SAFE};
275
276 match s.len() {
277 0 => Err(ParseAddrError::Empty),
278 66..=69 if format.allow_raw => Self::from_str(s).map(|addr| (addr, Default::default())),
279 48 if format.allow_base64 || format.allow_base64_url => {
280 let mut buffer = [0u8; 36];
281
282 let base64_url = s.contains(['_', '-']);
283
284 let Ok(36) = if base64_url {
285 BASE64_URL_SAFE
286 } else {
287 BASE64_STANDARD
288 }
289 .decode_slice(s, &mut buffer) else {
290 return Err(ParseAddrError::BadFormat);
291 };
292
293 #[cfg(not(fuzzing))]
294 {
295 let crc = crate::crc::crc_16(&buffer[..34]);
296 if buffer[34] as u16 != (crc >> 8) || buffer[35] as u16 != (crc & 0xff) {
297 return Err(ParseAddrError::BadFormat);
298 }
299 }
300
301 let addr = StdAddr::new(
302 buffer[1] as i8,
303 HashBytes(buffer[2..34].try_into().unwrap()),
304 );
305 let flags = Base64StdAddrFlags {
306 testnet: buffer[0] & 0x80 != 0,
307 base64_url,
308 bounceable: buffer[0] & 0x40 == 0,
309 };
310 Ok((addr, flags))
311 }
312 _ => Err(ParseAddrError::BadFormat),
313 }
314 }
315
316 #[inline]
320 pub const fn is_masterchain(&self) -> bool {
321 self.workchain as i32 == ShardIdent::MASTERCHAIN.workchain()
322 }
323
324 pub const fn bit_len(&self) -> u16 {
326 let mut bit_len = Self::BITS_WITHOUT_ANYCAST;
327 if let Some(anycast) = &self.anycast {
328 bit_len += anycast.bit_len();
329 }
330 bit_len
331 }
332
333 pub const fn prefix(&self) -> u64 {
335 u64::from_be_bytes(*self.address.first_chunk())
336 }
337
338 #[cfg(feature = "base64")]
340 pub const fn display_base64(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
341 DisplayBase64StdAddr {
342 addr: self,
343 flags: Base64StdAddrFlags {
344 testnet: false,
345 base64_url: false,
346 bounceable,
347 },
348 }
349 }
350
351 #[cfg(feature = "base64")]
353 pub const fn display_base64_url(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
354 DisplayBase64StdAddr {
355 addr: self,
356 flags: Base64StdAddrFlags {
357 testnet: false,
358 base64_url: true,
359 bounceable,
360 },
361 }
362 }
363}
364
365impl Addr for StdAddr {
366 #[inline]
367 fn workchain(&self) -> i32 {
368 self.workchain as i32
369 }
370
371 #[inline]
372 fn prefix(&self) -> u64 {
373 StdAddr::prefix(self)
374 }
375}
376
377impl std::fmt::Display for StdAddr {
378 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
379 if let Some(anycast) = &self.anycast {
380 ok!(f.write_fmt(format_args!("{anycast}:")))
381 }
382
383 f.write_fmt(format_args!("{}:{}", self.workchain, self.address))
384 }
385}
386
387impl From<(i8, HashBytes)> for StdAddr {
388 #[inline]
389 fn from((workchain, address): (i8, HashBytes)) -> Self {
390 Self::new(workchain, address)
391 }
392}
393
394impl From<(i8, [u8; 32])> for StdAddr {
395 #[inline]
396 fn from((workchain, address): (i8, [u8; 32])) -> Self {
397 Self::new(workchain, HashBytes(address))
398 }
399}
400
401impl From<StdAddr> for IntAddr {
402 #[inline]
403 fn from(value: StdAddr) -> Self {
404 Self::Std(value)
405 }
406}
407
408impl FromStr for StdAddr {
409 type Err = ParseAddrError;
410
411 fn from_str(s: &str) -> Result<Self, Self::Err> {
412 if s.is_empty() {
413 return Err(ParseAddrError::Empty);
414 }
415
416 let mut result = Self::default();
417
418 let mut parts = s.split(':');
419 match parts.next() {
420 Some(part) => match part.parse() {
421 Ok(workchain) => result.workchain = workchain,
422 Err(_) => return Err(ParseAddrError::InvalidWorkchain),
423 },
424 None => return Err(ParseAddrError::Empty),
425 }
426
427 match parts.next() {
428 Some(part) => match hex::decode_to_slice(part, &mut result.address.0) {
429 Ok(()) => {}
430 Err(_) => return Err(ParseAddrError::InvalidAccountId),
431 },
432 None => return Err(ParseAddrError::InvalidAccountId),
433 }
434
435 if parts.next().is_none() {
436 Ok(result)
437 } else {
438 Err(ParseAddrError::UnexpectedPart)
439 }
440 }
441}
442
443impl Store for StdAddr {
444 fn store_into(
445 &self,
446 builder: &mut CellBuilder,
447 context: &dyn CellContext,
448 ) -> Result<(), Error> {
449 if !builder.has_capacity(self.bit_len(), 0) {
450 return Err(Error::CellOverflow);
451 }
452 ok!(builder.store_small_uint(0b10, 2));
453 ok!(self.anycast.store_into(builder, context));
454 ok!(builder.store_u8(self.workchain as u8));
455 builder.store_u256(&self.address)
456 }
457}
458
459impl<'a> Load<'a> for StdAddr {
460 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
461 if !ok!(slice.load_bit()) || ok!(slice.load_bit()) {
462 return Err(Error::InvalidTag);
463 }
464
465 Ok(Self {
466 anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
467 workchain: ok!(slice.load_u8()) as i8,
468 address: ok!(slice.load_u256()),
469 })
470 }
471}
472
473impl crate::dict::DictKey for StdAddr {
474 const BITS: u16 = StdAddr::BITS_WITHOUT_ANYCAST;
475}
476
477impl crate::dict::StoreDictKey for StdAddr {
478 fn store_into_data(&self, builder: &mut CellDataBuilder) -> Result<(), Error> {
479 if self.anycast.is_some() || !builder.has_capacity_bits(Self::BITS_WITHOUT_ANYCAST) {
480 return Err(Error::InvalidData);
481 }
482 ok!(builder.store_small_uint(0b100, 3)); ok!(builder.store_u8(self.workchain as u8));
484 builder.store_u256(&self.address)
485 }
486}
487
488impl crate::dict::LoadDictKey for StdAddr {
489 fn load_from_data(data: &CellDataBuilder) -> Option<Self> {
490 let [first_byte, second_byte, data @ ..] = data.raw_data();
491
492 const PREFIX_BITS: u8 = 0b1000_0000;
495 const PREFIX_MASK: u8 = 0b1110_0000;
496
497 const R: u8 = 3;
498 const SHIFT: u8 = 8 - R;
499 const REV_SHIFT: u8 = 120 + R;
500
501 if unlikely((first_byte ^ PREFIX_BITS) & PREFIX_MASK != 0) {
502 return None;
503 }
504
505 let mut result = Self {
506 anycast: None,
507 workchain: ((first_byte << R) | (second_byte >> SHIFT)) as i8,
509 address: HashBytes::ZERO,
510 };
511
512 let [mut hi, mut lo]: [u128; 2] =
514 unsafe { std::mem::transmute::<[u8; 32], _>(data[..32].try_into().unwrap()) };
515
516 #[cfg(target_endian = "little")]
518 {
519 hi = hi.swap_bytes();
520 lo = lo.swap_bytes();
521 }
522
523 result.address = unsafe {
525 std::mem::transmute::<[[u8; 16]; 2], HashBytes>([
526 ((hi >> SHIFT) | ((*second_byte as u128) << REV_SHIFT)).to_be_bytes(),
527 ((lo >> SHIFT) | (hi << REV_SHIFT)).to_be_bytes(),
528 ])
529 };
530
531 Some(result)
532 }
533}
534
535#[cfg(feature = "serde")]
536impl serde::Serialize for StdAddr {
537 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
538 where
539 S: serde::Serializer,
540 {
541 if serializer.is_human_readable() {
542 serializer.collect_str(self)
543 } else {
544 (self.workchain, &self.address).serialize(serializer)
545 }
546 }
547}
548
549#[cfg(feature = "serde")]
550impl<'de> serde::Deserialize<'de> for StdAddr {
551 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
552 where
553 D: serde::Deserializer<'de>,
554 {
555 use serde::de::{Error, Visitor};
556
557 struct StdAddrVisitor;
558
559 impl Visitor<'_> for StdAddrVisitor {
560 type Value = StdAddr;
561
562 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
563 f.write_str("a standard address")
564 }
565
566 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
567 where
568 E: Error,
569 {
570 StdAddr::from_str(v).map_err(E::custom)
571 }
572 }
573
574 if deserializer.is_human_readable() {
575 deserializer.deserialize_str(StdAddrVisitor)
576 } else {
577 <(i8, HashBytes)>::deserialize(deserializer)
578 .map(|(workchain, address)| Self::new(workchain, address))
579 }
580 }
581}
582
583#[cfg(feature = "arbitrary")]
584impl<'a> arbitrary::Arbitrary<'a> for StdAddr {
585 #[inline]
586 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
587 Ok(Self {
588 anycast: u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?,
589 workchain: u.arbitrary()?,
590 address: u.arbitrary()?,
591 })
592 }
593
594 #[inline]
595 fn size_hint(depth: usize) -> (usize, Option<usize>) {
596 arbitrary::size_hint::and(Option::<Anycast>::size_hint(depth), (33, Some(33)))
597 }
598}
599
600#[cfg(feature = "base64")]
602pub struct StdAddrBase64Repr<const URL_SAFE: bool = true>;
603
604#[cfg(all(feature = "base64", feature = "serde"))]
605impl<const URL_SAFE: bool> StdAddrBase64Repr<URL_SAFE> {
606 pub fn serialize<S>(addr: &StdAddr, serializer: S) -> Result<S::Ok, S::Error>
608 where
609 S: serde::Serializer,
610 {
611 serializer.collect_str(&DisplayBase64StdAddr {
612 addr,
613 flags: Base64StdAddrFlags {
614 testnet: false,
615 base64_url: URL_SAFE,
616 bounceable: false,
617 },
618 })
619 }
620
621 pub fn deserialize<'de, D>(deserializer: D) -> Result<StdAddr, D::Error>
623 where
624 D: serde::Deserializer<'de>,
625 {
626 use serde::de::{Error, Visitor};
627
628 struct StdAddrBase64Visitor;
629
630 impl Visitor<'_> for StdAddrBase64Visitor {
631 type Value = StdAddr;
632
633 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
634 f.write_str("a standard address")
635 }
636
637 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
638 where
639 E: Error,
640 {
641 StdAddr::from_str_ext(v, StdAddrFormat::any())
642 .map(|(addr, _)| addr)
643 .map_err(E::custom)
644 }
645 }
646
647 deserializer.deserialize_str(StdAddrBase64Visitor)
648 }
649}
650
651#[cfg(feature = "base64")]
653#[derive(Debug, Clone, Copy)]
654pub struct StdAddrFormat {
655 pub allow_raw: bool,
657 pub allow_base64: bool,
659 pub allow_base64_url: bool,
661}
662
663#[cfg(feature = "base64")]
664impl StdAddrFormat {
665 pub const fn any() -> Self {
667 StdAddrFormat {
668 allow_raw: true,
669 allow_base64: true,
670 allow_base64_url: true,
671 }
672 }
673}
674
675#[cfg(feature = "base64")]
677#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
678pub struct Base64StdAddrFlags {
679 pub testnet: bool,
681 pub base64_url: bool,
683 pub bounceable: bool,
685}
686
687#[cfg(feature = "base64")]
689pub struct DisplayBase64StdAddr<'a> {
690 pub addr: &'a StdAddr,
692 pub flags: Base64StdAddrFlags,
694}
695
696#[cfg(feature = "base64")]
697impl std::fmt::Display for DisplayBase64StdAddr<'_> {
698 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
699 use base64::prelude::{Engine as _, BASE64_STANDARD, BASE64_URL_SAFE};
700
701 let mut buffer = [0u8; 36];
702 buffer[0] = (0x51 - (self.flags.bounceable as i32) * 0x40
703 + (self.flags.testnet as i32) * 0x80) as u8;
704 buffer[1] = self.addr.workchain as u8;
705 buffer[2..34].copy_from_slice(self.addr.address.as_array());
706
707 let crc = crate::crc::crc_16(&buffer[..34]);
708 buffer[34] = (crc >> 8) as u8;
709 buffer[35] = (crc & 0xff) as u8;
710
711 let mut output = [0u8; 48];
712 if self.flags.base64_url {
713 BASE64_URL_SAFE
714 } else {
715 BASE64_STANDARD
716 }
717 .encode_slice(buffer, &mut output)
718 .unwrap();
719
720 let output = unsafe { std::str::from_utf8_unchecked(&output) };
722 f.write_str(output)
723 }
724}
725
726#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
728pub struct VarAddr {
729 pub anycast: Option<Box<Anycast>>,
731 pub address_len: Uint9,
733 pub workchain: i32,
735 pub address: Vec<u8>,
737}
738
739impl VarAddr {
740 pub const BITS_MAX: u16 =
748 2 + 1 + Anycast::BITS_MAX + Uint9::BITS + 32 + Uint9::MAX.into_inner();
749
750 #[inline]
754 pub const fn is_masterchain(&self) -> bool {
755 self.workchain == ShardIdent::MASTERCHAIN.workchain()
756 }
757
758 pub const fn bit_len(&self) -> u16 {
760 let mut bit_len = 2 + 1 + Uint9::BITS + 32 + self.address_len.into_inner();
761 if let Some(anycast) = &self.anycast {
762 bit_len += anycast.bit_len();
763 }
764 bit_len
765 }
766
767 pub fn prefix(&self) -> u64 {
769 let mut prefix = [0; 8];
770 let total_bytes = std::cmp::min(self.address.len(), 8);
771 prefix[..total_bytes].copy_from_slice(&self.address[..total_bytes]);
772 u64::from_be_bytes(prefix)
773 }
774}
775
776impl From<VarAddr> for IntAddr {
777 #[inline]
778 fn from(value: VarAddr) -> Self {
779 Self::Var(value)
780 }
781}
782
783impl Store for VarAddr {
784 fn store_into(
785 &self,
786 builder: &mut CellBuilder,
787 context: &dyn CellContext,
788 ) -> Result<(), Error> {
789 if !builder.has_capacity(self.bit_len(), 0) {
790 return Err(Error::CellOverflow);
791 }
792 ok!(builder.store_small_uint(0b11, 2));
793 ok!(self.anycast.store_into(builder, context));
794 ok!(self.address_len.store_into(builder, context));
795 ok!(builder.store_u32(self.workchain as u32));
796 builder.store_raw(&self.address, self.address_len.into_inner())
797 }
798}
799
800impl Addr for VarAddr {
801 #[inline]
802 fn workchain(&self) -> i32 {
803 self.workchain
804 }
805
806 #[inline]
807 fn prefix(&self) -> u64 {
808 VarAddr::prefix(self)
809 }
810}
811
812#[cfg(feature = "arbitrary")]
813impl<'a> arbitrary::Arbitrary<'a> for VarAddr {
814 #[inline]
815 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
816 let anycast = u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?;
817 let address_len = u.arbitrary::<Uint9>()?;
818 let workchain = u.arbitrary()?;
819
820 let bit_len = address_len.into_inner() as usize;
821 let mut address = u.bytes(bit_len.div_ceil(8))?.to_vec();
822 if let Some(last_byte) = address.last_mut() {
823 let rem = bit_len % 8;
824 if rem != 0 {
825 *last_byte &= u8::MAX << (8 - rem);
826 }
827 }
828
829 Ok(Self {
830 anycast,
831 address_len,
832 workchain,
833 address,
834 })
835 }
836
837 #[inline]
838 fn size_hint(_: usize) -> (usize, Option<usize>) {
839 (1 + 2 + 4, None)
840 }
841}
842
843#[derive(Debug, Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
850pub struct ExtAddr {
851 pub data_bit_len: Uint9,
853 pub data: Vec<u8>,
855}
856
857impl ExtAddr {
858 pub fn new<T>(data_bit_len: u16, data: T) -> Option<Self>
860 where
861 T: Into<Vec<u8>>,
862 {
863 let data_bit_len = Uint9::new(data_bit_len);
864 if data_bit_len.is_valid() {
865 Some(Self {
866 data_bit_len,
867 data: data.into(),
868 })
869 } else {
870 None
871 }
872 }
873
874 pub const fn bit_len(&self) -> u16 {
876 Uint9::BITS + self.data_bit_len.into_inner()
877 }
878}
879
880impl std::fmt::Display for ExtAddr {
881 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
882 let bitstring = Bitstring {
883 bytes: &self.data,
884 bit_len: self.data_bit_len.into_inner(),
885 };
886 write!(f, ":{bitstring}")
887 }
888}
889
890impl FromStr for ExtAddr {
891 type Err = ParseAddrError;
892
893 fn from_str(s: &str) -> Result<Self, Self::Err> {
894 if s.is_empty() {
895 return Err(ParseAddrError::Empty);
896 }
897
898 let Some(s) = s.strip_prefix(':') else {
899 return Err(ParseAddrError::UnexpectedPart);
900 };
901
902 let Ok((data, bit_len)) = Bitstring::from_hex_str(s) else {
903 return Err(ParseAddrError::InvalidAccountId);
904 };
905
906 ExtAddr::new(bit_len, data).ok_or(ParseAddrError::UnexpectedPart)
907 }
908}
909
910#[cfg(feature = "serde")]
911impl serde::Serialize for ExtAddr {
912 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
913 if serializer.is_human_readable() {
914 serializer.collect_str(self)
915 } else {
916 (self.data_bit_len.into_inner(), &self.data).serialize(serializer)
917 }
918 }
919}
920
921#[cfg(feature = "serde")]
922impl<'de> serde::Deserialize<'de> for ExtAddr {
923 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
924 use serde::de::{Error, Visitor};
925
926 struct ExtAddrVisitor;
927
928 impl Visitor<'_> for ExtAddrVisitor {
929 type Value = ExtAddr;
930
931 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
932 f.write_str("an external address")
933 }
934
935 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
936 ExtAddr::from_str(v).map_err(E::custom)
937 }
938 }
939
940 if deserializer.is_human_readable() {
941 deserializer.deserialize_str(ExtAddrVisitor)
942 } else {
943 <(u16, Vec<u8>)>::deserialize(deserializer).and_then(|(data_bit_len, data)| {
944 ExtAddr::new(data_bit_len, data)
945 .ok_or_else(|| Error::custom("invalid external address data length"))
946 })
947 }
948 }
949}
950
951#[cfg(feature = "arbitrary")]
952impl<'a> arbitrary::Arbitrary<'a> for ExtAddr {
953 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
954 let data_bit_len = u.arbitrary::<Uint9>()?;
955
956 let bit_len = data_bit_len.into_inner() as usize;
957 let mut data = u.bytes(bit_len.div_ceil(8))?.to_vec();
958 if let Some(last_byte) = data.last_mut() {
959 let rem = bit_len % 8;
960 if rem != 0 {
961 *last_byte &= u8::MAX << (8 - rem);
962 }
963 }
964
965 Ok(Self { data_bit_len, data })
966 }
967
968 #[inline]
969 fn size_hint(_: usize) -> (usize, Option<usize>) {
970 (2, None)
971 }
972}
973
974#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
980pub struct Anycast {
981 pub depth: SplitDepth,
983 pub rewrite_prefix: Vec<u8>,
985}
986
987impl Anycast {
988 pub const MIN_DEPTH: u8 = 1;
990 pub const MAX_DEPTH: u8 = 30;
992
993 pub const BITS_MAX: u16 = SplitDepth::BITS + Self::MAX_DEPTH as u16;
995
996 pub fn from_slice(rewrite_prefix: &CellSlice<'_>) -> Result<Self, Error> {
998 let depth = ok!(SplitDepth::from_bit_len(rewrite_prefix.size_bits()));
999
1000 let mut data = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1001 ok!(rewrite_prefix.get_raw(0, &mut data, depth.into_bit_len()));
1002
1003 Ok(Self {
1004 depth,
1005 rewrite_prefix: data,
1006 })
1007 }
1008
1009 pub const fn bit_len(&self) -> u16 {
1011 SplitDepth::BITS + self.depth.into_bit_len()
1012 }
1013}
1014
1015impl std::fmt::Display for Anycast {
1016 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1017 let bitstring = Bitstring {
1018 bytes: &self.rewrite_prefix,
1019 bit_len: self.depth.into_bit_len(),
1020 };
1021 std::fmt::Display::fmt(&bitstring, f)
1022 }
1023}
1024
1025impl Store for Anycast {
1026 fn store_into(
1027 &self,
1028 builder: &mut CellBuilder,
1029 context: &dyn CellContext,
1030 ) -> Result<(), Error> {
1031 if !builder.has_capacity(self.bit_len(), 0) {
1032 return Err(Error::CellOverflow);
1033 }
1034 ok!(self.depth.store_into(builder, context));
1035 builder.store_raw(&self.rewrite_prefix, self.depth.into_bit_len())
1036 }
1037}
1038
1039impl<'a> Load<'a> for Anycast {
1040 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1041 let depth = ok!(SplitDepth::load_from(slice));
1042 if !slice.has_remaining(depth.into_bit_len(), 0) {
1043 return Err(Error::CellUnderflow);
1044 }
1045
1046 let mut rewrite_prefix = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1047 ok!(slice.load_raw(&mut rewrite_prefix, depth.into_bit_len()));
1048
1049 Ok(Self {
1050 depth,
1051 rewrite_prefix,
1052 })
1053 }
1054}
1055
1056#[cfg(feature = "arbitrary")]
1057impl<'a> arbitrary::Arbitrary<'a> for Anycast {
1058 #[inline]
1059 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1060 let split_depth = SplitDepth::arbitrary(u)?;
1061 let bit_len = split_depth.into_bit_len();
1062
1063 let bytes = u.bytes(bit_len.div_ceil(8) as _)?;
1064
1065 let b = CellBuilder::from_raw_data(bytes, bit_len).unwrap();
1066 Ok(Self::from_slice(&b.as_data_slice()).unwrap())
1067 }
1068
1069 #[inline]
1070 fn size_hint(_: usize) -> (usize, Option<usize>) {
1071 (2, Some(5))
1072 }
1073}
1074
1075#[cfg(test)]
1076mod tests {
1077 use super::*;
1078 use crate::dict::Dict;
1079
1080 #[test]
1081 fn dict_with_std_addr_keys() {
1082 let mut dict = Dict::<StdAddr, u32>::new();
1083 dict.set(StdAddr::new(-1, HashBytes([0x33; 32])), 123)
1084 .unwrap();
1085 dict.set(StdAddr::new(0, HashBytes([0x10; 32])), 321)
1086 .unwrap();
1087 dict.set(StdAddr::new(-1, HashBytes([0x55; 32])), 234)
1088 .unwrap();
1089 dict.set(StdAddr::new(0, HashBytes([0x20; 32])), 432)
1090 .unwrap();
1091
1092 for entry in dict.iter() {
1093 let (addr, value) = entry.unwrap();
1094 println!("{addr}: {value}");
1095 }
1096 }
1097
1098 #[test]
1099 fn anycast_str() {
1100 let empty_res = Anycast::from_slice(&Cell::empty_cell().as_slice().unwrap());
1102 assert_eq!(empty_res.unwrap_err(), Error::IntOverflow);
1103
1104 let mut prefix = CellBuilder::new();
1106 prefix.store_bit_one().unwrap();
1107 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1108 assert_eq!(anycast.to_string(), "c_");
1109
1110 let mut prefix = CellBuilder::new();
1112 prefix.store_u8(0xa5).unwrap();
1113 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1114 assert_eq!(anycast.to_string(), "a5");
1115
1116 let mut prefix = CellBuilder::new();
1118 prefix.store_uint(0xb00b1e5, 28).unwrap();
1119 prefix.store_zeros(2).unwrap();
1120 let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1121 assert_eq!(anycast.to_string(), "b00b1e52_");
1122 }
1123
1124 #[test]
1125 fn address_prefix() {
1126 let addr = "0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415"
1127 .parse::<StdAddr>()
1128 .unwrap();
1129 assert_eq!(addr.prefix(), 0xece57bcc6c530283);
1130
1131 let var_addr = VarAddr {
1132 anycast: None,
1133 address_len: Uint9::new(32),
1134 workchain: 0,
1135 address: vec![0xb0, 0xba, 0xca, 0xfe],
1136 };
1137 assert_eq!(var_addr.prefix(), 0xb0bacafe00000000);
1138
1139 let var_addr = VarAddr {
1140 anycast: None,
1141 address_len: Uint9::new(72),
1142 workchain: 0,
1143 address: vec![0xb0, 0xba, 0xca, 0xfe, 0xb0, 0x0b, 0x1e, 0x5a, 0xff],
1144 };
1145 assert_eq!(var_addr.prefix(), 0xb0bacafeb00b1e5a);
1146 }
1147
1148 #[test]
1149 fn base64_address() {
1150 let addr = "0:84545d4d2cada0ce811705d534c298ca42d29315d03a16eee794cefd191dfa79"
1151 .parse::<StdAddr>()
1152 .unwrap();
1153 assert_eq!(
1154 addr.display_base64(true).to_string(),
1155 "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw"
1156 );
1157 assert_eq!(
1158 StdAddr::from_str_ext(
1159 "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw",
1160 StdAddrFormat::any()
1161 )
1162 .unwrap(),
1163 (addr, Base64StdAddrFlags {
1164 testnet: false,
1165 base64_url: false,
1166 bounceable: true,
1167 })
1168 );
1169
1170 let addr = "0:dddde93b1d3398f0b4305c08de9a032e0bc1b257c4ce2c72090aea1ff3e9ecfd"
1171 .parse::<StdAddr>()
1172 .unwrap();
1173 assert_eq!(
1174 addr.display_base64_url(false).to_string(),
1175 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_Tyv"
1176 );
1177 assert_eq!(
1178 addr.display_base64(false).to_string(),
1179 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv"
1180 );
1181
1182 assert_eq!(
1183 StdAddr::from_str_ext(
1184 "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv",
1185 StdAddrFormat::any()
1186 )
1187 .unwrap(),
1188 (addr.clone(), Base64StdAddrFlags {
1189 testnet: false,
1190 base64_url: false,
1191 bounceable: false,
1192 })
1193 );
1194
1195 assert_eq!(
1196 addr.display_base64_url(true).to_string(),
1197 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq"
1198 );
1199 assert_eq!(
1200 addr.display_base64(true).to_string(),
1201 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/WFq"
1202 );
1203
1204 assert_eq!(
1205 StdAddr::from_str_ext(
1206 "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq",
1207 StdAddrFormat::any()
1208 )
1209 .unwrap(),
1210 (addr, Base64StdAddrFlags {
1211 testnet: false,
1212 base64_url: true,
1213 bounceable: true,
1214 })
1215 );
1216 }
1217}