1use std::borrow::Borrow;
4
5pub use self::address::*;
6pub use self::envelope::*;
7pub use self::in_message::*;
8pub use self::out_message::*;
9use crate::cell::*;
10use crate::error::Error;
11use crate::models::account::StateInit;
12use crate::models::currency::CurrencyCollection;
13use crate::num::*;
14
15mod address;
16mod envelope;
17mod in_message;
18mod out_message;
19#[cfg(test)]
20mod tests;
21
22pub type Message<'a> = BaseMessage<MsgInfo, CellSlice<'a>>;
24
25impl EquivalentRepr<OwnedMessage> for Message<'_> {}
26impl EquivalentRepr<RelaxedMessage<'_>> for Message<'_> {}
27impl EquivalentRepr<OwnedRelaxedMessage> for Message<'_> {}
28
29pub type OwnedMessage = BaseMessage<MsgInfo, CellSliceParts>;
31
32impl EquivalentRepr<Message<'_>> for OwnedMessage {}
33impl EquivalentRepr<RelaxedMessage<'_>> for OwnedMessage {}
34impl EquivalentRepr<OwnedRelaxedMessage> for OwnedMessage {}
35
36pub type RelaxedMessage<'a> = BaseMessage<RelaxedMsgInfo, CellSlice<'a>>;
38
39impl EquivalentRepr<Message<'_>> for RelaxedMessage<'_> {}
40impl EquivalentRepr<OwnedMessage> for RelaxedMessage<'_> {}
41impl EquivalentRepr<OwnedRelaxedMessage> for RelaxedMessage<'_> {}
42
43pub type OwnedRelaxedMessage = BaseMessage<RelaxedMsgInfo, CellSliceParts>;
45
46impl EquivalentRepr<Message<'_>> for OwnedRelaxedMessage {}
47impl EquivalentRepr<OwnedMessage> for OwnedRelaxedMessage {}
48impl EquivalentRepr<RelaxedMessage<'_>> for OwnedRelaxedMessage {}
49
50#[derive(Debug, Clone)]
52pub struct BaseMessage<I, B> {
53 pub info: I,
55 pub init: Option<StateInit>,
57 pub body: B,
59 pub layout: Option<MessageLayout>,
61}
62
63#[cfg(feature = "serde")]
64impl<I, B> serde::Serialize for BaseMessage<I, B>
65where
66 I: ExactSize + Store + serde::Serialize,
67 B: ExactSize + StoreBody,
68{
69 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
70 use serde::ser::{Error, SerializeStruct};
71
72 struct BodySerializer<'a, B: StoreBody>(&'a B);
73
74 impl<B: StoreBody> serde::Serialize for BodySerializer<'_, B> {
75 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
76 let mut builder = CellBuilder::new();
77 ok!(self
78 .0
79 .store_body(false, &mut builder, Cell::empty_context())
80 .map_err(Error::custom));
81 let cell = ok!(builder.build().map_err(Error::custom));
82 crate::boc::Boc::serialize(&cell, serializer)
83 }
84 }
85
86 if serializer.is_human_readable() {
87 let mut ser = ok!(serializer.serialize_struct("Message", 4));
88 ok!(ser.serialize_field("info", &self.info));
89 ok!(ser.serialize_field("init", &self.init));
90 ok!(ser.serialize_field("body", &BodySerializer(&self.body)));
91 ok!(ser.serialize_field("layout", &self.layout));
92 ser.end()
93 } else {
94 crate::boc::BocRepr::serialize(self, serializer)
95 }
96 }
97}
98
99#[cfg(feature = "serde")]
100impl<'de, I> serde::Deserialize<'de> for BaseMessage<I, CellSliceParts>
101where
102 for<'a> I: ExactSize + Load<'a> + serde::Deserialize<'de>,
103{
104 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
105 where
106 D: serde::Deserializer<'de>,
107 {
108 #[derive(serde::Deserialize)]
109 struct Message<I> {
110 info: I,
111 #[serde(default)]
112 init: Option<StateInit>,
113 #[serde(with = "crate::boc::Boc", default)]
114 body: Cell,
115 #[serde(default)]
116 layout: Option<MessageLayout>,
117 }
118
119 if deserializer.is_human_readable() {
120 let msg = Message::deserialize(deserializer)?;
121 Ok(Self {
122 info: msg.info,
123 init: msg.init,
124 body: msg.body.into(),
125 layout: msg.layout,
126 })
127 } else {
128 crate::boc::BocRepr::deserialize(deserializer)
129 }
130 }
131}
132
133#[cfg(feature = "arbitrary")]
134impl<'a, I: arbitrary::Arbitrary<'a>> arbitrary::Arbitrary<'a> for BaseMessage<I, CellSliceParts> {
135 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
136 Ok(Self {
137 info: u.arbitrary()?,
138 init: u.arbitrary()?,
139 body: u.arbitrary::<Cell>()?.into(),
140 layout: u.arbitrary()?,
141 })
142 }
143
144 fn size_hint(depth: usize) -> (usize, Option<usize>) {
145 Self::try_size_hint(depth).unwrap_or_default()
146 }
147
148 fn try_size_hint(
149 depth: usize,
150 ) -> arbitrary::Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
151 Ok(arbitrary::size_hint::and_all(&[
152 <I as arbitrary::Arbitrary>::try_size_hint(depth)?,
153 <Option<StateInit> as arbitrary::Arbitrary>::try_size_hint(depth)?,
154 <Cell as arbitrary::Arbitrary>::try_size_hint(depth)?,
155 <Option<MessageLayout> as arbitrary::Arbitrary>::try_size_hint(depth)?,
156 ]))
157 }
158}
159
160impl<I: Borrow<MsgInfo>, B> BaseMessage<I, B> {
161 pub fn ty(&self) -> MsgType {
163 self.info.borrow().ty()
164 }
165}
166
167impl<I: ExactSize, B: ExactSize> BaseMessage<I, B> {
168 pub fn compute_layout(info: &I, init: Option<&StateInit>, body: &B) -> MessageLayout {
170 let (layout, ..) = MessageLayout::compute(info.exact_size(), init, body.exact_size());
171 layout
172 }
173}
174
175impl<I, B> Store for BaseMessage<I, B>
176where
177 I: Store + ExactSize,
178 B: StoreBody + ExactSize,
179{
180 fn store_into(
181 &self,
182 builder: &mut CellBuilder,
183 context: &dyn CellContext,
184 ) -> Result<(), Error> {
185 let info_size = self.info.exact_size();
186 let body_size = self.body.exact_size();
187 let (layout, size) = match self.layout {
188 Some(layout) => {
189 let size = layout.compute_full_size(info_size, self.init.as_ref(), body_size);
190 (layout, size)
191 }
192 None => MessageLayout::compute(info_size, self.init.as_ref(), body_size),
193 };
194 let Size { bits, refs } = size;
195
196 if !builder.has_capacity(bits, refs) {
198 return Err(Error::CellOverflow);
199 }
200
201 ok!(self.info.store_into(builder, context));
203
204 ok!(match &self.init {
206 Some(value) => {
207 ok!(builder.store_bit_one()); SliceOrCell {
209 to_cell: layout.init_to_cell,
210 value,
211 }
212 .store_into(builder, context)
213 }
214 None => builder.store_bit_zero(), });
216
217 ok!(builder.store_bit(layout.body_to_cell));
219 self.body.store_body(layout.body_to_cell, builder, context)
220 }
221}
222
223impl<'a, I, B> Load<'a> for BaseMessage<I, B>
224where
225 I: Load<'a>,
226 B: LoadBody<'a>,
227{
228 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
229 let info = ok!(I::load_from(slice));
230 let init = ok!(Option::<SliceOrCell<StateInit>>::load_from(slice));
231
232 let body_to_cell = ok!(slice.load_bit());
233 let body = ok!(B::load_body(body_to_cell, slice));
234
235 let (init, init_to_cell) = match init {
236 Some(SliceOrCell { to_cell, value }) => (Some(value), to_cell),
237 None => (None, false),
238 };
239
240 let layout = MessageLayout {
241 init_to_cell,
242 body_to_cell,
243 };
244
245 Ok(Self {
246 info,
247 init,
248 body,
249 layout: Some(layout),
250 })
251 }
252}
253
254trait StoreBody {
255 fn store_body(
256 &self,
257 to_cell: bool,
258 builder: &mut CellBuilder,
259 context: &dyn CellContext,
260 ) -> Result<(), Error>;
261}
262
263impl StoreBody for CellSlice<'_> {
264 fn store_body(
265 &self,
266 to_cell: bool,
267 builder: &mut CellBuilder,
268 context: &dyn CellContext,
269 ) -> Result<(), Error> {
270 SliceOrCell {
271 to_cell,
272 value: self,
273 }
274 .store_only_value_into(builder, context)
275 }
276}
277
278impl StoreBody for CellSliceParts {
279 fn store_body(
280 &self,
281 to_cell: bool,
282 builder: &mut CellBuilder,
283 context: &dyn CellContext,
284 ) -> Result<(), Error> {
285 let (range, cell) = self;
286 if to_cell && range.is_full(cell.as_ref()) {
287 builder.store_reference(cell.clone())
288 } else {
289 SliceOrCell {
290 to_cell,
291 value: ok!(range.apply(cell)),
292 }
293 .store_only_value_into(builder, context)
294 }
295 }
296}
297
298trait LoadBody<'a>: Sized {
299 fn load_body(from_cell: bool, slice: &mut CellSlice<'a>) -> Result<Self, Error>;
300}
301
302impl<'a> LoadBody<'a> for CellSlice<'a> {
303 fn load_body(from_cell: bool, slice: &mut CellSlice<'a>) -> Result<Self, Error> {
304 if from_cell {
305 slice.load_reference_as_slice()
306 } else {
307 Ok(slice.load_remaining())
308 }
309 }
310}
311
312impl<'a> LoadBody<'a> for CellSliceParts {
313 fn load_body(from_cell: bool, slice: &mut CellSlice<'a>) -> Result<Self, Error> {
314 if from_cell {
315 slice.load_reference_cloned()
316 } else {
317 let slice = slice.load_remaining();
318 let mut builder = CellBuilder::new();
319 ok!(builder.store_slice(slice));
320 builder.build()
321 }
322 .map(From::from)
323 }
324}
325
326struct SliceOrCell<T> {
327 to_cell: bool,
328 value: T,
329}
330
331impl<T: Store> SliceOrCell<T> {
332 fn store_only_value_into(
333 &self,
334 builder: &mut CellBuilder,
335 context: &dyn CellContext,
336 ) -> Result<(), Error> {
337 if self.to_cell {
338 let cell = {
339 let mut builder = CellBuilder::new();
340 ok!(self.value.store_into(&mut builder, context));
341 ok!(builder.build_ext(context))
342 };
343 builder.store_reference(cell)
344 } else {
345 self.value.store_into(builder, context)
346 }
347 }
348}
349
350impl<T: Store> Store for SliceOrCell<T> {
351 fn store_into(
352 &self,
353 builder: &mut CellBuilder,
354 context: &dyn CellContext,
355 ) -> Result<(), Error> {
356 ok!(builder.store_bit(self.to_cell));
357 self.store_only_value_into(builder, context)
358 }
359}
360
361impl<'a, T: Load<'a>> Load<'a> for SliceOrCell<T> {
362 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
363 let to_cell = ok!(slice.load_bit());
364
365 let mut child_cell = if to_cell {
366 Some(ok!(slice.load_reference_as_slice()))
367 } else {
368 None
369 };
370
371 let slice = match &mut child_cell {
372 Some(slice) => slice,
373 None => slice,
374 };
375
376 Ok(Self {
377 to_cell,
378 value: ok!(T::load_from(slice)),
379 })
380 }
381}
382
383#[derive(Debug, Copy, Clone, Eq, PartialEq)]
385#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
386#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
387pub struct MessageLayout {
388 pub init_to_cell: bool,
390 pub body_to_cell: bool,
392}
393
394impl MessageLayout {
395 #[inline]
397 pub const fn plain() -> Self {
398 Self {
399 init_to_cell: false,
400 body_to_cell: false,
401 }
402 }
403
404 pub const fn compute_full_size(
406 &self,
407 info_size: Size,
408 init: Option<&StateInit>,
409 body_size: Size,
410 ) -> Size {
411 let l = DetailedMessageLayout::compute(info_size, init, body_size);
412
413 let mut total = l.info;
414
415 if self.init_to_cell {
417 total.refs += 1;
418 } else {
419 total.bits += l.init.bits;
420 total.refs += l.init.refs;
421 }
422
423 if self.body_to_cell {
425 total.refs += 1;
426 } else {
427 total.bits += l.body.bits;
428 total.refs += l.body.refs;
429 }
430
431 total
432 }
433
434 pub const fn compute(
437 info_size: Size,
438 init: Option<&StateInit>,
439 body_size: Size,
440 ) -> (Self, Size) {
441 let l = DetailedMessageLayout::compute(info_size, init, body_size);
442
443 let total_bits = l.info.bits + l.init.bits + l.body.bits;
445 let total_refs = l.info.refs + l.init.refs + l.body.refs;
446 if total_bits <= MAX_BIT_LEN && total_refs <= MAX_REF_COUNT as u8 {
447 let layout = Self {
448 init_to_cell: false,
449 body_to_cell: false,
450 };
451 return (layout, Size {
452 bits: total_bits,
453 refs: total_refs,
454 });
455 }
456
457 let total_bits = l.info.bits + l.init.bits;
459 let total_refs = l.info.refs + l.init.refs;
460 if total_bits <= MAX_BIT_LEN && total_refs < MAX_REF_COUNT as u8 {
461 let layout = Self {
462 init_to_cell: false,
463 body_to_cell: true,
464 };
465 return (layout, Size {
466 bits: total_bits,
467 refs: total_refs + 1,
468 });
469 }
470
471 let total_bits = l.info.bits + l.body.bits;
473 let total_refs = l.info.refs + l.body.refs;
474 if total_bits <= MAX_BIT_LEN && total_refs < MAX_REF_COUNT as u8 {
475 let layout = Self {
476 init_to_cell: true,
477 body_to_cell: false,
478 };
479 return (layout, Size {
480 bits: total_bits,
481 refs: total_refs + 1,
482 });
483 }
484
485 let layout = Self {
487 init_to_cell: true,
488 body_to_cell: true,
489 };
490 (layout, Size {
491 bits: l.info.bits,
492 refs: l.info.refs + 2,
493 })
494 }
495}
496
497struct DetailedMessageLayout {
498 info: Size,
499 init: Size,
500 body: Size,
501}
502
503impl DetailedMessageLayout {
504 const fn compute(mut info: Size, init: Option<&StateInit>, body: Size) -> Self {
505 info.bits += 2; let init = match init {
508 Some(init) => {
509 info.bits += 1; init.exact_size_const()
511 }
512 None => Size::ZERO,
513 };
514
515 Self { info, init, body }
516 }
517}
518
519#[derive(Debug, Clone, Eq, PartialEq)]
521#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
522#[cfg_attr(feature = "serde", serde(tag = "ty"))]
523#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
524pub enum RelaxedMsgInfo {
525 Int(RelaxedIntMsgInfo),
527 ExtOut(RelaxedExtOutMsgInfo),
529}
530
531impl RelaxedMsgInfo {
532 pub const fn exact_size_const(&self) -> Size {
534 Size {
535 bits: self.bit_len(),
536 refs: self.has_references() as u8,
537 }
538 }
539
540 const fn bit_len(&self) -> u16 {
542 match self {
543 Self::Int(info) => info.bit_len(),
544 Self::ExtOut(info) => info.bit_len(),
545 }
546 }
547
548 const fn has_references(&self) -> bool {
549 match self {
550 Self::Int(info) => !info.value.other.is_empty(),
551 _ => false,
552 }
553 }
554}
555
556impl From<RelaxedIntMsgInfo> for RelaxedMsgInfo {
557 #[inline]
558 fn from(info: RelaxedIntMsgInfo) -> Self {
559 Self::Int(info)
560 }
561}
562
563impl From<RelaxedExtOutMsgInfo> for RelaxedMsgInfo {
564 #[inline]
565 fn from(info: RelaxedExtOutMsgInfo) -> Self {
566 Self::ExtOut(info)
567 }
568}
569
570impl From<IntMsgInfo> for RelaxedMsgInfo {
571 #[inline]
572 fn from(info: IntMsgInfo) -> Self {
573 Self::Int(RelaxedIntMsgInfo {
574 ihr_disabled: info.ihr_disabled,
575 bounce: info.bounce,
576 bounced: info.bounced,
577 src: Some(info.src),
578 dst: info.dst,
579 value: info.value,
580 ihr_fee: info.ihr_fee,
581 fwd_fee: info.fwd_fee,
582 created_lt: info.created_lt,
583 created_at: info.created_at,
584 })
585 }
586}
587
588impl From<ExtOutMsgInfo> for RelaxedMsgInfo {
589 #[inline]
590 fn from(info: ExtOutMsgInfo) -> Self {
591 Self::ExtOut(RelaxedExtOutMsgInfo {
592 src: Some(info.src),
593 dst: info.dst,
594 created_lt: info.created_lt,
595 created_at: info.created_at,
596 })
597 }
598}
599
600impl ExactSize for RelaxedMsgInfo {
601 #[inline]
602 fn exact_size(&self) -> Size {
603 self.exact_size_const()
604 }
605}
606
607impl Store for RelaxedMsgInfo {
608 fn store_into(
609 &self,
610 builder: &mut CellBuilder,
611 context: &dyn CellContext,
612 ) -> Result<(), Error> {
613 match self {
614 Self::Int(info) => {
615 ok!(builder.store_bit_zero());
616 info.store_into(builder, context)
617 }
618 Self::ExtOut(info) => {
619 ok!(builder.store_small_uint(0b11, 2));
620 info.store_into(builder, context)
621 }
622 }
623 }
624}
625
626impl<'a> Load<'a> for RelaxedMsgInfo {
627 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
628 Ok(if !ok!(slice.load_bit()) {
629 match RelaxedIntMsgInfo::load_from(slice) {
630 Ok(info) => Self::Int(info),
631 Err(e) => return Err(e),
632 }
633 } else if ok!(slice.load_bit()) {
634 match RelaxedExtOutMsgInfo::load_from(slice) {
635 Ok(info) => Self::ExtOut(info),
636 Err(e) => return Err(e),
637 }
638 } else {
639 return Err(Error::InvalidTag);
640 })
641 }
642}
643
644#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
646#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
647pub enum MsgType {
648 Int,
650 ExtIn,
652 ExtOut,
654}
655
656impl MsgType {
657 pub const fn is_internal(&self) -> bool {
659 matches!(self, Self::Int)
660 }
661
662 pub const fn is_external_in(&self) -> bool {
664 matches!(self, Self::ExtIn)
665 }
666
667 pub const fn is_external_out(&self) -> bool {
669 matches!(self, Self::ExtOut)
670 }
671}
672
673impl Store for MsgType {
674 fn store_into(&self, b: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
675 match self {
676 Self::Int => b.store_bit_zero(),
677 Self::ExtIn => b.store_small_uint(0b10, 2),
678 Self::ExtOut => b.store_small_uint(0b11, 2),
679 }
680 }
681}
682
683impl<'a> Load<'a> for MsgType {
684 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
685 Ok(if !ok!(slice.load_bit()) {
686 Self::Int
687 } else if !ok!(slice.load_bit()) {
688 Self::ExtIn
689 } else {
690 Self::ExtOut
691 })
692 }
693}
694
695#[derive(Debug, Clone, Eq, PartialEq)]
697#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
698#[cfg_attr(feature = "serde", serde(tag = "ty"))]
699#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
700pub enum MsgInfo {
701 Int(IntMsgInfo),
703 ExtIn(ExtInMsgInfo),
705 ExtOut(ExtOutMsgInfo),
707}
708
709impl MsgInfo {
710 pub const fn ty(&self) -> MsgType {
712 match self {
713 Self::Int(_) => MsgType::Int,
714 Self::ExtIn(_) => MsgType::ExtIn,
715 Self::ExtOut(_) => MsgType::ExtOut,
716 }
717 }
718
719 pub const fn is_internal(&self) -> bool {
721 matches!(self, Self::Int(_))
722 }
723
724 pub const fn is_external_in(&self) -> bool {
726 matches!(self, Self::ExtIn(_))
727 }
728
729 pub const fn is_external_out(&self) -> bool {
731 matches!(self, Self::ExtOut(_))
732 }
733
734 pub const fn exact_size_const(&self) -> Size {
736 Size {
737 bits: self.bit_len(),
738 refs: self.has_references() as u8,
739 }
740 }
741
742 const fn bit_len(&self) -> u16 {
744 match self {
745 Self::Int(info) => info.bit_len(),
746 Self::ExtIn(info) => info.bit_len(),
747 Self::ExtOut(info) => info.bit_len(),
748 }
749 }
750
751 const fn has_references(&self) -> bool {
752 match self {
753 Self::Int(info) => !info.value.other.is_empty(),
754 _ => false,
755 }
756 }
757}
758
759impl ExactSize for MsgInfo {
760 #[inline]
761 fn exact_size(&self) -> Size {
762 self.exact_size_const()
763 }
764}
765
766impl Store for MsgInfo {
767 fn store_into(
768 &self,
769 builder: &mut CellBuilder,
770 context: &dyn CellContext,
771 ) -> Result<(), Error> {
772 match self {
773 Self::Int(info) => {
774 ok!(builder.store_bit_zero());
775 info.store_into(builder, context)
776 }
777 Self::ExtIn(info) => {
778 ok!(builder.store_small_uint(0b10, 2));
779 info.store_into(builder, context)
780 }
781 Self::ExtOut(info) => {
782 ok!(builder.store_small_uint(0b11, 2));
783 info.store_into(builder, context)
784 }
785 }
786 }
787}
788
789impl<'a> Load<'a> for MsgInfo {
790 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
791 Ok(if !ok!(slice.load_bit()) {
792 match IntMsgInfo::load_from(slice) {
793 Ok(info) => Self::Int(info),
794 Err(e) => return Err(e),
795 }
796 } else if !ok!(slice.load_bit()) {
797 match ExtInMsgInfo::load_from(slice) {
798 Ok(info) => Self::ExtIn(info),
799 Err(e) => return Err(e),
800 }
801 } else {
802 match ExtOutMsgInfo::load_from(slice) {
803 Ok(info) => Self::ExtOut(info),
804 Err(e) => return Err(e),
805 }
806 })
807 }
808}
809
810impl From<IntMsgInfo> for MsgInfo {
811 #[inline]
812 fn from(value: IntMsgInfo) -> Self {
813 Self::Int(value)
814 }
815}
816
817impl From<ExtInMsgInfo> for MsgInfo {
818 #[inline]
819 fn from(value: ExtInMsgInfo) -> Self {
820 Self::ExtIn(value)
821 }
822}
823
824impl From<ExtOutMsgInfo> for MsgInfo {
825 #[inline]
826 fn from(value: ExtOutMsgInfo) -> Self {
827 Self::ExtOut(value)
828 }
829}
830
831#[derive(Debug, Clone, Eq, PartialEq)]
833#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
834#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
835pub struct IntMsgInfo {
836 pub ihr_disabled: bool,
838 pub bounce: bool,
840 pub bounced: bool,
842 pub src: IntAddr,
844 pub dst: IntAddr,
846 pub value: CurrencyCollection,
848 pub ihr_fee: Tokens,
852 pub fwd_fee: Tokens,
854 pub created_lt: u64,
856 pub created_at: u32,
858}
859
860impl Default for IntMsgInfo {
861 fn default() -> Self {
862 Self {
863 ihr_disabled: true,
864 bounce: false,
865 bounced: false,
866 src: Default::default(),
867 dst: Default::default(),
868 value: CurrencyCollection::ZERO,
869 ihr_fee: Default::default(),
870 fwd_fee: Default::default(),
871 created_lt: 0,
872 created_at: 0,
873 }
874 }
875}
876
877impl IntMsgInfo {
878 pub const fn bit_len(&self) -> u16 {
880 3 + self.src.bit_len()
881 + self.dst.bit_len()
882 + self.value.bit_len()
883 + self.ihr_fee.unwrap_bit_len()
884 + self.fwd_fee.unwrap_bit_len()
885 + 64
886 + 32
887 }
888}
889
890impl Store for IntMsgInfo {
891 fn store_into(
892 &self,
893 builder: &mut CellBuilder,
894 context: &dyn CellContext,
895 ) -> Result<(), Error> {
896 let flags =
897 ((self.ihr_disabled as u8) << 2) | ((self.bounce as u8) << 1) | self.bounced as u8;
898 ok!(builder.store_small_uint(flags, 3));
899 ok!(self.src.store_into(builder, context));
900 ok!(self.dst.store_into(builder, context));
901 ok!(self.value.store_into(builder, context));
902 ok!(self.ihr_fee.store_into(builder, context));
903 ok!(self.fwd_fee.store_into(builder, context));
904 ok!(builder.store_u64(self.created_lt));
905 builder.store_u32(self.created_at)
906 }
907}
908
909impl<'a> Load<'a> for IntMsgInfo {
910 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
911 let flags = ok!(slice.load_small_uint(3));
912 Ok(Self {
913 ihr_disabled: flags & 0b100 != 0,
914 bounce: flags & 0b010 != 0,
915 bounced: flags & 0b001 != 0,
916 src: ok!(IntAddr::load_from(slice)),
917 dst: ok!(IntAddr::load_from(slice)),
918 value: ok!(CurrencyCollection::load_from(slice)),
919 ihr_fee: ok!(Tokens::load_from(slice)),
920 fwd_fee: ok!(Tokens::load_from(slice)),
921 created_lt: ok!(slice.load_u64()),
922 created_at: ok!(slice.load_u32()),
923 })
924 }
925}
926
927#[derive(Debug, Clone, Eq, PartialEq)]
929#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
930#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
931pub struct RelaxedIntMsgInfo {
932 pub ihr_disabled: bool,
934 pub bounce: bool,
936 pub bounced: bool,
938 pub src: Option<IntAddr>,
940 pub dst: IntAddr,
942 pub value: CurrencyCollection,
944 pub ihr_fee: Tokens,
948 pub fwd_fee: Tokens,
950 pub created_lt: u64,
952 pub created_at: u32,
954}
955
956impl Default for RelaxedIntMsgInfo {
957 fn default() -> Self {
958 Self {
959 ihr_disabled: true,
960 bounce: false,
961 bounced: false,
962 src: Default::default(),
963 dst: Default::default(),
964 value: CurrencyCollection::ZERO,
965 ihr_fee: Default::default(),
966 fwd_fee: Default::default(),
967 created_lt: 0,
968 created_at: 0,
969 }
970 }
971}
972
973impl RelaxedIntMsgInfo {
974 pub const fn bit_len(&self) -> u16 {
976 3 + compute_opt_int_addr_bit_len(&self.src)
977 + self.dst.bit_len()
978 + self.value.bit_len()
979 + self.ihr_fee.unwrap_bit_len()
980 + self.fwd_fee.unwrap_bit_len()
981 + 64
982 + 32
983 }
984}
985
986impl Store for RelaxedIntMsgInfo {
987 fn store_into(
988 &self,
989 builder: &mut CellBuilder,
990 context: &dyn CellContext,
991 ) -> Result<(), Error> {
992 let flags =
993 ((self.ihr_disabled as u8) << 2) | ((self.bounce as u8) << 1) | self.bounced as u8;
994 ok!(builder.store_small_uint(flags, 3));
995 ok!(store_opt_int_addr(builder, context, &self.src));
996 ok!(self.dst.store_into(builder, context));
997 ok!(self.value.store_into(builder, context));
998 ok!(self.ihr_fee.store_into(builder, context));
999 ok!(self.fwd_fee.store_into(builder, context));
1000 ok!(builder.store_u64(self.created_lt));
1001 builder.store_u32(self.created_at)
1002 }
1003}
1004
1005impl<'a> Load<'a> for RelaxedIntMsgInfo {
1006 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1007 let flags = ok!(slice.load_small_uint(3));
1008 Ok(Self {
1009 ihr_disabled: flags & 0b100 != 0,
1010 bounce: flags & 0b010 != 0,
1011 bounced: flags & 0b001 != 0,
1012 src: ok!(load_opt_int_addr(slice)),
1013 dst: ok!(IntAddr::load_from(slice)),
1014 value: ok!(CurrencyCollection::load_from(slice)),
1015 ihr_fee: ok!(Tokens::load_from(slice)),
1016 fwd_fee: ok!(Tokens::load_from(slice)),
1017 created_lt: ok!(slice.load_u64()),
1018 created_at: ok!(slice.load_u32()),
1019 })
1020 }
1021}
1022
1023#[derive(Debug, Default, Clone, Eq, PartialEq)]
1025#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1026#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1027pub struct ExtInMsgInfo {
1028 #[cfg_attr(
1030 feature = "serde",
1031 serde(default, skip_serializing_if = "Option::is_none")
1032 )]
1033 pub src: Option<ExtAddr>,
1034 pub dst: IntAddr,
1036 pub import_fee: Tokens,
1040}
1041
1042impl ExtInMsgInfo {
1043 pub const fn bit_len(&self) -> u16 {
1045 2 + compute_ext_addr_bit_len(&self.src)
1046 + self.dst.bit_len()
1047 + self.import_fee.unwrap_bit_len()
1048 }
1049}
1050
1051impl Store for ExtInMsgInfo {
1052 fn store_into(
1053 &self,
1054 builder: &mut CellBuilder,
1055 context: &dyn CellContext,
1056 ) -> Result<(), Error> {
1057 if !self.import_fee.is_valid() {
1058 return Err(Error::InvalidData);
1059 }
1060 if !builder.has_capacity(self.bit_len(), 0) {
1061 return Err(Error::CellOverflow);
1062 }
1063 ok!(store_ext_addr(builder, context, &self.src));
1064 ok!(self.dst.store_into(builder, context));
1065 self.import_fee.store_into(builder, context)
1066 }
1067}
1068
1069impl<'a> Load<'a> for ExtInMsgInfo {
1070 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1071 Ok(Self {
1072 src: ok!(load_ext_addr(slice)),
1073 dst: ok!(IntAddr::load_from(slice)),
1074 import_fee: ok!(Tokens::load_from(slice)),
1075 })
1076 }
1077}
1078
1079#[derive(Debug, Default, Clone, Eq, PartialEq)]
1081#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1082#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1083pub struct ExtOutMsgInfo {
1084 pub src: IntAddr,
1086 #[cfg_attr(
1088 feature = "serde",
1089 serde(default, skip_serializing_if = "Option::is_none")
1090 )]
1091 pub dst: Option<ExtAddr>,
1092 pub created_lt: u64,
1094 pub created_at: u32,
1096}
1097
1098impl ExtOutMsgInfo {
1099 pub const fn bit_len(&self) -> u16 {
1101 2 + self.src.bit_len() + compute_ext_addr_bit_len(&self.dst) + 64 + 32
1102 }
1103}
1104
1105impl Store for ExtOutMsgInfo {
1106 fn store_into(
1107 &self,
1108 builder: &mut CellBuilder,
1109 context: &dyn CellContext,
1110 ) -> Result<(), Error> {
1111 if !builder.has_capacity(self.bit_len(), 0) {
1112 return Err(Error::CellOverflow);
1113 }
1114 ok!(self.src.store_into(builder, context));
1115 ok!(store_ext_addr(builder, context, &self.dst));
1116 ok!(builder.store_u64(self.created_lt));
1117 builder.store_u32(self.created_at)
1118 }
1119}
1120
1121impl<'a> Load<'a> for ExtOutMsgInfo {
1122 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1123 Ok(Self {
1124 src: ok!(IntAddr::load_from(slice)),
1125 dst: ok!(load_ext_addr(slice)),
1126 created_lt: ok!(slice.load_u64()),
1127 created_at: ok!(slice.load_u32()),
1128 })
1129 }
1130}
1131
1132#[derive(Debug, Default, Clone, Eq, PartialEq)]
1134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1135#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1136pub struct RelaxedExtOutMsgInfo {
1137 pub src: Option<IntAddr>,
1139 #[cfg_attr(
1141 feature = "serde",
1142 serde(default, skip_serializing_if = "Option::is_none")
1143 )]
1144 pub dst: Option<ExtAddr>,
1145 pub created_lt: u64,
1147 pub created_at: u32,
1149}
1150
1151impl RelaxedExtOutMsgInfo {
1152 pub const fn bit_len(&self) -> u16 {
1154 2 + compute_opt_int_addr_bit_len(&self.src) + compute_ext_addr_bit_len(&self.dst) + 64 + 32
1155 }
1156}
1157
1158impl Store for RelaxedExtOutMsgInfo {
1159 fn store_into(
1160 &self,
1161 builder: &mut CellBuilder,
1162 context: &dyn CellContext,
1163 ) -> Result<(), Error> {
1164 ok!(store_opt_int_addr(builder, context, &self.src));
1165 ok!(store_ext_addr(builder, context, &self.dst));
1166 ok!(builder.store_u64(self.created_lt));
1167 builder.store_u32(self.created_at)
1168 }
1169}
1170
1171impl<'a> Load<'a> for RelaxedExtOutMsgInfo {
1172 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1173 Ok(Self {
1174 src: ok!(load_opt_int_addr(slice)),
1175 dst: ok!(load_ext_addr(slice)),
1176 created_lt: ok!(slice.load_u64()),
1177 created_at: ok!(slice.load_u32()),
1178 })
1179 }
1180}
1181
1182const fn compute_ext_addr_bit_len(addr: &Option<ExtAddr>) -> u16 {
1183 match addr {
1184 Some(addr) => 2 + addr.bit_len(),
1185 None => 2,
1186 }
1187}
1188
1189fn store_ext_addr(
1190 builder: &mut CellBuilder,
1191 context: &dyn CellContext,
1192 addr: &Option<ExtAddr>,
1193) -> Result<(), Error> {
1194 match addr {
1195 None => builder.store_zeros(2),
1196 Some(ExtAddr { data_bit_len, data }) => {
1197 if !builder.has_capacity(2 + Uint9::BITS + data_bit_len.into_inner(), 0) {
1198 return Err(Error::CellOverflow);
1199 }
1200 ok!(builder.store_bit_zero());
1201 ok!(builder.store_bit_one());
1202 ok!(data_bit_len.store_into(builder, context));
1203 builder.store_raw(data, data_bit_len.into_inner())
1204 }
1205 }
1206}
1207
1208fn load_ext_addr(slice: &mut CellSlice<'_>) -> Result<Option<ExtAddr>, Error> {
1209 if ok!(slice.load_bit()) {
1210 return Err(Error::InvalidTag);
1211 }
1212
1213 if !ok!(slice.load_bit()) {
1214 return Ok(None);
1215 }
1216
1217 let data_bit_len = ok!(Uint9::load_from(slice));
1218 if !slice.has_remaining(data_bit_len.into_inner(), 0) {
1219 return Err(Error::CellUnderflow);
1220 }
1221
1222 let mut data = vec![0; data_bit_len.into_inner().div_ceil(8) as usize];
1223 ok!(slice.load_raw(&mut data, data_bit_len.into_inner()));
1224 Ok(Some(ExtAddr { data_bit_len, data }))
1225}
1226
1227const fn compute_opt_int_addr_bit_len(addr: &Option<IntAddr>) -> u16 {
1228 match addr {
1229 Some(src) => src.bit_len(),
1230 None => 2,
1231 }
1232}
1233
1234fn store_opt_int_addr(
1235 builder: &mut CellBuilder,
1236 context: &dyn CellContext,
1237 addr: &Option<IntAddr>,
1238) -> Result<(), Error> {
1239 match addr {
1240 Some(addr) => addr.store_into(builder, context),
1241 None => builder.store_zeros(2),
1242 }
1243}
1244
1245fn load_opt_int_addr(slice: &mut CellSlice<'_>) -> Result<Option<IntAddr>, Error> {
1246 if ok!(slice.get_bit(0)) {
1247 IntAddr::load_from(slice).map(Some)
1248 } else if ok!(slice.load_small_uint(2)) == 0b00 {
1249 Ok(None)
1250 } else {
1251 Err(Error::InvalidTag)
1252 }
1253}