roam_frame/
owned_message.rs1#![allow(unsafe_code)]
3
4use std::mem::ManuallyDrop;
5
6use crate::Frame;
7
8pub struct OwnedMessage<T: 'static> {
16 value: ManuallyDrop<T>,
17 frame: ManuallyDrop<Box<Frame>>,
18}
19
20impl<T: 'static> Drop for OwnedMessage<T> {
21 fn drop(&mut self) {
22 unsafe {
24 ManuallyDrop::drop(&mut self.value);
25 ManuallyDrop::drop(&mut self.frame);
26 }
27 }
28}
29
30impl<T: 'static + facet::Facet<'static>> OwnedMessage<T> {
31 #[inline]
32 pub fn try_new<E>(
33 frame: Frame,
34 builder: impl FnOnce(&'static [u8]) -> Result<T, E>,
35 ) -> Result<Self, E> {
36 let variance = T::SHAPE.computed_variance();
37 assert!(
38 variance.can_shrink(),
39 "OwnedMessage<T> requires T to be covariant (lifetime can shrink safely). Type {:?} has variance {:?}",
40 T::SHAPE.type_identifier,
41 variance
42 );
43
44 let frame = Box::new(frame);
45
46 let payload: &'static [u8] = unsafe {
52 let bytes = (*frame).payload_bytes();
53 std::slice::from_raw_parts(bytes.as_ptr(), bytes.len())
54 };
55
56 let value = builder(payload)?;
57
58 Ok(Self {
59 value: ManuallyDrop::new(value),
60 frame: ManuallyDrop::new(frame),
61 })
62 }
63
64 #[inline]
65 pub fn new(frame: Frame, builder: impl FnOnce(&'static [u8]) -> T) -> Self {
66 Self::try_new(frame, |payload| {
67 Ok::<_, std::convert::Infallible>(builder(payload))
68 })
69 .unwrap_or_else(|e: std::convert::Infallible| match e {})
70 }
71}
72
73impl<T: 'static> OwnedMessage<T> {
74 #[inline]
75 pub fn frame(&self) -> &Frame {
76 &self.frame
77 }
78
79 #[inline]
80 pub fn value(&self) -> &T {
81 &self.value
82 }
83
84 #[inline]
85 pub fn into_frame(mut self) -> Frame {
86 unsafe {
87 ManuallyDrop::drop(&mut self.value);
88 }
89 let frame = unsafe { ManuallyDrop::take(&mut self.frame) };
90 std::mem::forget(self);
91 *frame
92 }
93}
94
95impl<T: 'static> std::ops::Deref for OwnedMessage<T> {
96 type Target = T;
97
98 #[inline]
99 fn deref(&self) -> &T {
100 &self.value
101 }
102}
103
104impl<T: 'static> AsRef<T> for OwnedMessage<T> {
105 #[inline]
106 fn as_ref(&self) -> &T {
107 &self.value
108 }
109}
110
111impl<T: 'static + std::fmt::Debug> std::fmt::Debug for OwnedMessage<T> {
112 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 f.debug_struct("OwnedMessage")
114 .field("value", &*self.value)
115 .finish_non_exhaustive()
116 }
117}