1use std::cmp::Ordering;
12use std::fmt;
13use std::hash::Hash;
14use std::hash::Hasher;
15use std::marker::PhantomData;
16
17use derivative::Derivative;
18use hyperactor_config::Flattrs;
19use serde::Deserialize;
20use serde::Deserializer;
21use serde::Serialize;
22use serde::Serializer;
23use typeuri::Named;
24
25use crate::Actor;
26use crate::ActorAddr;
27use crate::ActorHandle;
28use crate::Endpoint;
29use crate::EndpointLocation;
30use crate::PortAddr;
31use crate::RemoteEndpoint;
32use crate::RemoteHandles;
33use crate::RemoteMessage;
34use crate::accum::ReducerSpec;
35use crate::accum::StreamingReducerOpts;
36use crate::actor::Binds;
37use crate::actor::Referable;
38use crate::context;
39use crate::context::MailboxExt;
40use crate::mailbox::DeliveryFailureReport;
41use crate::mailbox::MailboxSenderError;
42use crate::mailbox::MailboxSenderErrorKind;
43use crate::mailbox::PortSink;
44use crate::port::Port;
45
46#[derive(typeuri::Named)]
48pub struct ActorRef<A: Referable> {
49 pub(crate) actor_addr: ActorAddr,
50 phantom: PhantomData<fn() -> A>,
52}
53
54impl<A: Referable> ActorRef<A> {
55 pub fn port<M: RemoteMessage>(&self) -> PortRef<M>
57 where
58 A: RemoteHandles<M>,
59 {
60 PortRef::attest(self.actor_addr.port_addr(Port::handler::<M>()))
61 }
62
63 pub fn attest(actor_addr: ActorAddr) -> Self {
68 Self {
69 actor_addr,
70 phantom: PhantomData,
71 }
72 }
73
74 pub fn actor_addr(&self) -> &ActorAddr {
76 &self.actor_addr
77 }
78
79 pub fn into_actor_addr(self) -> ActorAddr {
81 self.actor_addr
82 }
83
84 pub fn downcast_handle(&self, cx: &impl context::Actor) -> Option<ActorHandle<A>>
88 where
89 A: Actor,
90 {
91 cx.instance().proc().resolve_actor_ref(self)
92 }
93}
94
95impl<A, B> From<&ActorRef<A>> for ActorRef<B>
96where
97 A: Actor + Referable,
98 B: Binds<A>,
99{
100 fn from(value: &ActorRef<A>) -> Self {
101 ActorRef::attest(value.actor_addr().clone())
102 }
103}
104
105impl<A, M> Endpoint<M> for &ActorRef<A>
106where
107 A: Referable + RemoteHandles<M>,
108 M: RemoteMessage,
109{
110 fn endpoint_location(&self) -> EndpointLocation {
111 EndpointLocation::Actor(self.actor_addr.clone())
112 }
113
114 fn post<C>(self, cx: &C, message: M)
115 where
116 C: context::Actor,
117 {
118 RemoteEndpoint::post_with_headers(self, cx, Flattrs::new(), message)
119 }
120}
121
122impl<A, M> RemoteEndpoint<M> for &ActorRef<A>
123where
124 A: Referable + RemoteHandles<M>,
125 M: RemoteMessage,
126{
127 fn post_with_headers<C>(self, cx: &C, headers: Flattrs, message: M)
128 where
129 C: context::Actor,
130 {
131 RemoteEndpoint::post_with_headers(&self.port(), cx, headers, message)
132 }
133}
134
135impl<A: Referable> Serialize for ActorRef<A> {
137 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
138 where
139 S: Serializer,
140 {
141 self.actor_addr.serialize(serializer)
143 }
144}
145
146impl<'de, A: Referable> Deserialize<'de> for ActorRef<A> {
148 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
149 where
150 D: Deserializer<'de>,
151 {
152 let actor_addr = <ActorAddr>::deserialize(deserializer)?;
153 Ok(ActorRef {
154 actor_addr,
155 phantom: PhantomData,
156 })
157 }
158}
159
160impl<A: Referable> fmt::Debug for ActorRef<A> {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 f.debug_struct("ActorRef")
164 .field("actor_addr", &self.actor_addr)
165 .field("type", &std::any::type_name::<A>())
166 .finish()
167 }
168}
169
170impl<A: Referable> fmt::Display for ActorRef<A> {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 fmt::Display::fmt(&self.actor_addr, f)?;
173 write!(f, "<{}>", std::any::type_name::<A>())
174 }
175}
176
177impl<A: Referable> Clone for ActorRef<A> {
179 fn clone(&self) -> Self {
180 Self {
181 actor_addr: self.actor_addr.clone(),
182 phantom: PhantomData,
183 }
184 }
185}
186
187impl<A: Referable> PartialEq for ActorRef<A> {
188 fn eq(&self, other: &Self) -> bool {
189 self.actor_addr == other.actor_addr
190 }
191}
192
193impl<A: Referable> Eq for ActorRef<A> {}
194
195impl<A: Referable> PartialOrd for ActorRef<A> {
196 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
197 Some(self.cmp(other))
198 }
199}
200
201impl<A: Referable> Ord for ActorRef<A> {
202 fn cmp(&self, other: &Self) -> Ordering {
203 self.actor_addr.cmp(&other.actor_addr)
204 }
205}
206
207impl<A: Referable> Hash for ActorRef<A> {
208 fn hash<H: Hasher>(&self, state: &mut H) {
209 self.actor_addr.hash(state);
210 }
211}
212
213#[derive(Debug, Derivative, typeuri::Named)]
216#[derivative(PartialEq, Eq, PartialOrd, Hash, Ord)]
217pub struct PortRef<M> {
218 port_addr: PortAddr,
219 #[derivative(
220 PartialEq = "ignore",
221 PartialOrd = "ignore",
222 Ord = "ignore",
223 Hash = "ignore"
224 )]
225 reducer_spec: Option<ReducerSpec>,
226 #[derivative(
227 PartialEq = "ignore",
228 PartialOrd = "ignore",
229 Ord = "ignore",
230 Hash = "ignore"
231 )]
232 streaming_opts: StreamingReducerOpts,
233 phantom: PhantomData<M>,
234 return_undeliverable: bool,
235 #[derivative(
236 PartialEq = "ignore",
237 PartialOrd = "ignore",
238 Ord = "ignore",
239 Hash = "ignore"
240 )]
241 unsplit: bool,
242}
243
244#[doc(hidden)]
245#[derive(Debug, Clone, Serialize, Deserialize, typeuri::Named)]
246pub struct PortRefRepr {
247 port_addr: PortAddr,
248 reducer_spec: Option<ReducerSpec>,
249 streaming_opts: StreamingReducerOpts,
250 return_undeliverable: bool,
251 unsplit: bool,
252}
253
254impl PortRefRepr {
255 pub fn port_addr(&self) -> &PortAddr {
257 &self.port_addr
258 }
259
260 pub fn reducer_spec(&self) -> &Option<ReducerSpec> {
262 &self.reducer_spec
263 }
264
265 pub fn streaming_opts(&self) -> &StreamingReducerOpts {
267 &self.streaming_opts
268 }
269
270 pub fn get_return_undeliverable(&self) -> bool {
272 self.return_undeliverable
273 }
274
275 pub fn unsplit(&self) -> bool {
277 self.unsplit
278 }
279
280 pub fn update_port_addr(&mut self, port_addr: PortAddr) {
282 self.port_addr = port_addr;
283 }
284}
285
286impl<M> TryFrom<&PortRef<M>> for PortRefRepr {
287 type Error = serde_multipart::Error;
288
289 fn try_from(port_ref: &PortRef<M>) -> serde_multipart::Result<Self> {
290 Ok(Self {
291 port_addr: port_ref.port_addr.clone(),
292 reducer_spec: port_ref.reducer_spec.clone(),
293 streaming_opts: port_ref.streaming_opts.clone(),
294 return_undeliverable: port_ref.return_undeliverable,
295 unsplit: port_ref.unsplit,
296 })
297 }
298}
299
300impl<M> TryFrom<PortRefRepr> for PortRef<M> {
301 type Error = serde_multipart::Error;
302
303 fn try_from(repr: PortRefRepr) -> serde_multipart::Result<Self> {
304 Ok(Self {
305 port_addr: repr.port_addr,
306 reducer_spec: repr.reducer_spec,
307 streaming_opts: repr.streaming_opts,
308 phantom: PhantomData,
309 return_undeliverable: repr.return_undeliverable,
310 unsplit: repr.unsplit,
311 })
312 }
313}
314
315serde_multipart::part_codec! {
316 impl<M> PortRef<M>
317 {
318 type Repr = PortRefRepr;
319 }
320}
321
322impl<M: RemoteMessage> PortRef<M> {
323 pub fn attest(port_addr: PortAddr) -> Self {
326 Self {
327 port_addr,
328 reducer_spec: None,
329 streaming_opts: StreamingReducerOpts::default(),
330 phantom: PhantomData,
331 return_undeliverable: true,
332 unsplit: false,
333 }
334 }
335
336 pub fn attest_reducible(
339 port_addr: PortAddr,
340 reducer_spec: Option<ReducerSpec>,
341 streaming_opts: StreamingReducerOpts,
342 ) -> Self {
343 Self {
344 port_addr,
345 reducer_spec,
346 streaming_opts,
347 phantom: PhantomData,
348 return_undeliverable: true,
349 unsplit: false,
350 }
351 }
352
353 pub fn unsplit(mut self) -> Self {
355 self.unsplit = true;
356 self
357 }
358
359 pub fn attest_handler_port(actor: &ActorAddr) -> Self {
362 PortRef::<M>::attest(actor.port_addr(Port::handler::<M>()))
363 }
364
365 pub fn reducer_spec(&self) -> &Option<ReducerSpec> {
368 &self.reducer_spec
369 }
370
371 pub fn port_addr(&self) -> &PortAddr {
373 &self.port_addr
374 }
375
376 pub fn into_port_addr(self) -> PortAddr {
378 self.port_addr
379 }
380
381 pub fn into_once(self) -> OncePortRef<M> {
384 let return_undeliverable = self.return_undeliverable;
385 let unsplit = self.unsplit;
386 let mut once = OncePortRef::attest(self.into_port_addr());
387 once.return_undeliverable = return_undeliverable;
388 once.unsplit = unsplit;
389 once
390 }
391
392 pub fn post_serialized(
395 &self,
396 cx: &impl context::Actor,
397 mut headers: Flattrs,
398 message: wirevalue::Any,
399 ) {
400 crate::mailbox::headers::set_send_timestamp(&mut headers);
401 crate::mailbox::headers::set_rust_message_type::<M>(&mut headers);
402 cx.post(
403 self.port_addr.clone(),
404 headers,
405 message,
406 self.return_undeliverable,
407 context::SeqInfoPolicy::AssignNew,
408 );
409 }
410
411 pub fn into_sink<C: context::Actor>(self, cx: C) -> PortSink<C, M> {
413 PortSink::new(cx, self)
414 }
415
416 pub fn get_return_undeliverable(&self) -> bool {
419 self.return_undeliverable
420 }
421
422 pub fn return_undeliverable(&mut self, return_undeliverable: bool) {
425 self.return_undeliverable = return_undeliverable;
426 }
427}
428
429impl<M> Endpoint<M> for &PortRef<M>
430where
431 M: RemoteMessage,
432{
433 fn endpoint_location(&self) -> EndpointLocation {
434 EndpointLocation::Port(self.port_addr.clone())
435 }
436
437 fn post<C>(self, cx: &C, message: M)
438 where
439 C: context::Actor,
440 {
441 RemoteEndpoint::post_with_headers(self, cx, Flattrs::new(), message)
442 }
443}
444
445impl<M> RemoteEndpoint<M> for &PortRef<M>
446where
447 M: RemoteMessage,
448{
449 fn post_with_headers<C>(self, cx: &C, headers: Flattrs, message: M)
450 where
451 C: context::Actor,
452 {
453 let serialized = match wirevalue::Any::serialize(&message).map_err(|err| {
454 MailboxSenderError::new_bound(
455 self.port_addr.clone(),
456 MailboxSenderErrorKind::Serialize(err.into()),
457 )
458 }) {
459 Ok(serialized) => serialized,
460 Err(err) => {
461 cx.instance()
462 .report_delivery_failure(DeliveryFailureReport::from_send_error::<M>(
463 cx.mailbox().actor_addr().clone(),
464 self.endpoint_location(),
465 &err,
466 ));
467 return;
468 }
469 };
470 self.post_serialized(cx, headers, serialized);
471 }
472}
473
474impl<M: RemoteMessage> Clone for PortRef<M> {
475 fn clone(&self) -> Self {
476 Self {
477 port_addr: self.port_addr.clone(),
478 reducer_spec: self.reducer_spec.clone(),
479 streaming_opts: self.streaming_opts.clone(),
480 phantom: PhantomData,
481 return_undeliverable: self.return_undeliverable,
482 unsplit: self.unsplit,
483 }
484 }
485}
486
487impl<M: RemoteMessage> fmt::Display for PortRef<M> {
488 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
489 fmt::Display::fmt(&self.port_addr, f)
490 }
491}
492
493#[derive(Debug, PartialEq)]
497pub struct OncePortRef<M> {
498 port_addr: PortAddr,
499 reducer_spec: Option<ReducerSpec>,
500 return_undeliverable: bool,
501 unsplit: bool,
502 phantom: PhantomData<M>,
503}
504
505#[doc(hidden)]
506#[derive(Debug, Clone, Serialize, Deserialize, typeuri::Named)]
507pub struct OncePortRefRepr {
508 port_addr: PortAddr,
509 reducer_spec: Option<ReducerSpec>,
510 return_undeliverable: bool,
511 unsplit: bool,
512}
513
514impl OncePortRefRepr {
515 pub fn port_addr(&self) -> &PortAddr {
517 &self.port_addr
518 }
519
520 pub fn reducer_spec(&self) -> &Option<ReducerSpec> {
522 &self.reducer_spec
523 }
524
525 pub fn get_return_undeliverable(&self) -> bool {
527 self.return_undeliverable
528 }
529
530 pub fn unsplit(&self) -> bool {
532 self.unsplit
533 }
534
535 pub fn update_port_addr(&mut self, port_addr: PortAddr) {
537 self.port_addr = port_addr;
538 }
539}
540
541impl<M> TryFrom<&OncePortRef<M>> for OncePortRefRepr {
542 type Error = serde_multipart::Error;
543
544 fn try_from(port_ref: &OncePortRef<M>) -> serde_multipart::Result<Self> {
545 Ok(Self {
546 port_addr: port_ref.port_addr.clone(),
547 reducer_spec: port_ref.reducer_spec.clone(),
548 return_undeliverable: port_ref.return_undeliverable,
549 unsplit: port_ref.unsplit,
550 })
551 }
552}
553
554impl<M> TryFrom<OncePortRefRepr> for OncePortRef<M> {
555 type Error = serde_multipart::Error;
556
557 fn try_from(repr: OncePortRefRepr) -> serde_multipart::Result<Self> {
558 Ok(Self {
559 port_addr: repr.port_addr,
560 reducer_spec: repr.reducer_spec,
561 return_undeliverable: repr.return_undeliverable,
562 unsplit: repr.unsplit,
563 phantom: PhantomData,
564 })
565 }
566}
567
568serde_multipart::part_codec! {
569 impl<M> OncePortRef<M>
570 {
571 type Repr = OncePortRefRepr;
572 }
573}
574
575impl<M: RemoteMessage> OncePortRef<M> {
576 pub(crate) fn attest(port_addr: PortAddr) -> Self {
577 Self {
578 port_addr,
579 reducer_spec: None,
580 return_undeliverable: true,
581 unsplit: false,
582 phantom: PhantomData,
583 }
584 }
585
586 pub fn attest_reducible(port_addr: PortAddr, reducer_spec: Option<ReducerSpec>) -> Self {
589 Self {
590 port_addr,
591 reducer_spec,
592 return_undeliverable: true,
593 unsplit: false,
594 phantom: PhantomData,
595 }
596 }
597
598 pub fn unsplit(mut self) -> Self {
600 self.unsplit = true;
601 self
602 }
603
604 pub fn reducer_spec(&self) -> &Option<ReducerSpec> {
606 &self.reducer_spec
607 }
608
609 pub fn port_addr(&self) -> &PortAddr {
611 &self.port_addr
612 }
613
614 pub fn into_port_addr(self) -> PortAddr {
616 self.port_addr
617 }
618
619 pub fn get_return_undeliverable(&self) -> bool {
622 self.return_undeliverable
623 }
624
625 pub fn return_undeliverable(&mut self, return_undeliverable: bool) {
628 self.return_undeliverable = return_undeliverable;
629 }
630}
631
632impl<M> Endpoint<M> for OncePortRef<M>
633where
634 M: RemoteMessage,
635{
636 fn endpoint_location(&self) -> EndpointLocation {
637 EndpointLocation::Port(self.port_addr.clone())
638 }
639
640 fn post<C>(self, cx: &C, message: M)
641 where
642 C: context::Actor,
643 {
644 RemoteEndpoint::post_with_headers(self, cx, Flattrs::new(), message)
645 }
646}
647
648impl<M> RemoteEndpoint<M> for OncePortRef<M>
649where
650 M: RemoteMessage,
651{
652 fn post_with_headers<C>(self, cx: &C, mut headers: Flattrs, message: M)
653 where
654 C: context::Actor,
655 {
656 crate::mailbox::headers::set_send_timestamp(&mut headers);
657 let serialized = match wirevalue::Any::serialize(&message).map_err(|err| {
658 MailboxSenderError::new_bound(
659 self.port_addr.clone(),
660 MailboxSenderErrorKind::Serialize(err.into()),
661 )
662 }) {
663 Ok(serialized) => serialized,
664 Err(err) => {
665 cx.instance()
666 .report_delivery_failure(DeliveryFailureReport::from_send_error::<M>(
667 cx.mailbox().actor_addr().clone(),
668 self.endpoint_location(),
669 &err,
670 ));
671 return;
672 }
673 };
674 cx.post(
675 self.port_addr.clone(),
676 headers,
677 serialized,
678 self.return_undeliverable,
679 context::SeqInfoPolicy::AssignNew,
680 );
681 }
682}
683
684impl<M: RemoteMessage> Clone for OncePortRef<M> {
685 fn clone(&self) -> Self {
686 Self {
687 port_addr: self.port_addr.clone(),
688 reducer_spec: self.reducer_spec.clone(),
689 return_undeliverable: self.return_undeliverable,
690 unsplit: self.unsplit,
691 phantom: PhantomData,
692 }
693 }
694}
695
696impl<M: RemoteMessage> fmt::Display for OncePortRef<M> {
697 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
698 fmt::Display::fmt(&self.port_addr, f)
699 }
700}
701
702impl<M: RemoteMessage> Named for OncePortRef<M> {
703 fn typename() -> &'static str {
704 wirevalue::intern_typename!(Self, "hyperactor::mailbox::OncePortRef<{}>", M)
705 }
706}
707
708#[cfg(test)]
709mod tests {
710 use serde::Deserialize;
711 use serde::Serialize;
712 use serde_multipart::PartCodec;
713 use typeuri::Named;
714
715 use super::*;
716 use crate::channel::ChannelAddr;
717 use crate::id::ActorId;
718 use crate::id::Label;
719 use crate::id::PortId;
720 use crate::id::ProcId;
721
722 fn test_port_ref() -> PortRef<String> {
723 let proc_id = ProcId::singleton(Label::new("proc").unwrap());
724 let actor_id = ActorId::singleton(Label::new("actor").unwrap(), proc_id);
725 let port_id = PortId::new(actor_id, Port::from(7));
726 let port_addr = PortAddr::new(port_id, ChannelAddr::Local(42).into());
727 let mut port_ref = PortRef::<String>::attest(port_addr).unsplit();
728 port_ref.return_undeliverable(false);
729 port_ref
730 }
731
732 fn test_once_port_ref() -> OncePortRef<String> {
733 let proc_id = ProcId::singleton(Label::new("proc").unwrap());
734 let actor_id = ActorId::singleton(Label::new("actor").unwrap(), proc_id);
735 let port_id = PortId::new(actor_id, Port::from(8));
736 let port_addr = PortAddr::new(port_id, ChannelAddr::Local(43).into());
737 let mut once_port_ref = OncePortRef::<String>::attest(port_addr).unsplit();
738 once_port_ref.return_undeliverable(false);
739 once_port_ref
740 }
741
742 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
743 struct PortRefEnvelope {
744 port: PortRef<String>,
745 seq: u64,
746 }
747
748 #[derive(Debug, PartialEq, Serialize, Deserialize)]
749 struct OncePortRefEnvelope {
750 port: OncePortRef<String>,
751 seq: u64,
752 }
753
754 fn assert_same_port_ref(actual: &PortRef<String>, expected: &PortRef<String>) {
755 let actual = actual.to_repr().unwrap();
756 let expected = expected.to_repr().unwrap();
757 assert_eq!(actual.port_addr, expected.port_addr);
758 assert_eq!(actual.reducer_spec, expected.reducer_spec);
759 assert_eq!(actual.streaming_opts, expected.streaming_opts);
760 assert_eq!(actual.return_undeliverable, expected.return_undeliverable);
761 assert_eq!(actual.unsplit, expected.unsplit);
762 }
763
764 fn assert_same_once_port_ref(actual: &OncePortRef<String>, expected: &OncePortRef<String>) {
765 let actual = actual.to_repr().unwrap();
766 let expected = expected.to_repr().unwrap();
767 assert_eq!(actual.port_addr, expected.port_addr);
768 assert_eq!(actual.reducer_spec, expected.reducer_spec);
769 assert_eq!(actual.return_undeliverable, expected.return_undeliverable);
770 assert_eq!(actual.unsplit, expected.unsplit);
771 }
772
773 #[test]
774 fn test_port_ref_serde_multipart_part_codec() {
775 let value = PortRefEnvelope {
776 port: test_port_ref(),
777 seq: 123,
778 };
779
780 let message = serde_multipart::serialize_bincode(&value).unwrap();
781 assert_eq!(message.num_parts(), 1);
782 assert_eq!(message.parts()[0].typehash(), Some(PortRefRepr::typehash()));
783
784 let repr = message.parts()[0].deserialized::<PortRefRepr>().unwrap();
785 assert_eq!(repr.port_addr, value.port.port_addr().clone());
786 assert!(!repr.return_undeliverable);
787 assert!(repr.unsplit);
788
789 let deserialized: PortRefEnvelope = serde_multipart::deserialize_bincode(message).unwrap();
790 assert_eq!(deserialized.seq, value.seq);
791 assert_same_port_ref(&deserialized.port, &value.port);
792 }
793
794 #[test]
795 fn test_once_port_ref_serde_multipart_part_codec() {
796 let value = OncePortRefEnvelope {
797 port: test_once_port_ref(),
798 seq: 789,
799 };
800
801 let message = serde_multipart::serialize_bincode(&value).unwrap();
802 assert_eq!(message.num_parts(), 1);
803 assert_eq!(
804 message.parts()[0].typehash(),
805 Some(OncePortRefRepr::typehash())
806 );
807
808 let repr = message.parts()[0]
809 .deserialized::<OncePortRefRepr>()
810 .unwrap();
811 assert_eq!(repr.port_addr, value.port.port_addr().clone());
812 assert!(!repr.return_undeliverable);
813 assert!(repr.unsplit);
814
815 let deserialized: OncePortRefEnvelope =
816 serde_multipart::deserialize_bincode(message).unwrap();
817 assert_eq!(deserialized.seq, value.seq);
818 assert_same_once_port_ref(&deserialized.port, &value.port);
819 }
820
821 #[test]
822 fn test_port_ref_regular_serde_uses_repr() {
823 let value = PortRefEnvelope {
824 port: test_port_ref(),
825 seq: 456,
826 };
827
828 let encoded = bincode::serde::encode_to_vec(&value, bincode::config::standard()).unwrap();
829 let (deserialized, len): (PortRefEnvelope, usize) =
830 bincode::serde::decode_from_slice(&encoded, bincode::config::standard()).unwrap();
831
832 assert_eq!(len, encoded.len());
833 assert_eq!(deserialized.seq, value.seq);
834 assert_same_port_ref(&deserialized.port, &value.port);
835 }
836
837 #[test]
838 fn test_once_port_ref_regular_serde_uses_repr() {
839 let value = OncePortRefEnvelope {
840 port: test_once_port_ref(),
841 seq: 1011,
842 };
843
844 let encoded = bincode::serde::encode_to_vec(&value, bincode::config::standard()).unwrap();
845 let (deserialized, len): (OncePortRefEnvelope, usize) =
846 bincode::serde::decode_from_slice(&encoded, bincode::config::standard()).unwrap();
847
848 assert_eq!(len, encoded.len());
849 assert_eq!(deserialized.seq, value.seq);
850 assert_same_once_port_ref(&deserialized.port, &value.port);
851 }
852}