mesh_protobuf/
encode_with.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Helper type for mesh-encoding a type that must first be translated to
5//! another type.
6
7use super::DefaultEncoding;
8use super::InplaceOption;
9use super::MessageDecode;
10use super::MessageEncode;
11use super::Result;
12use super::encoding::MessageEncoding;
13use super::fmt;
14use super::protobuf::MessageReader;
15use super::protobuf::MessageSizer;
16use super::protobuf::MessageWriter;
17use crate::inplace;
18use core::ops::Deref;
19use core::ops::DerefMut;
20
21/// Wrapper type to easily support custom mesh encoding.
22///
23/// This type acts as `T` but encodes on a mesh channel as `U`. This is useful
24/// when `T` cannot be encoded directly via the derive macro but can be
25/// converted to a type that can be encoded directly.
26pub struct EncodeAs<T, U>(Inner<T, U>);
27
28pub struct EncodedMessage<E>(E);
29
30#[derive(Copy, Clone)]
31enum Inner<T, U> {
32    Unencoded(T),
33    Encoded(U),
34    Invalid,
35}
36
37impl<T, U> Deref for EncodeAs<T, U> {
38    type Target = T;
39
40    fn deref(&self) -> &Self::Target {
41        match &self.0 {
42            Inner::Unencoded(v) => v,
43            _ => unreachable!(),
44        }
45    }
46}
47
48impl<T, U> DerefMut for EncodeAs<T, U> {
49    fn deref_mut(&mut self) -> &mut Self::Target {
50        match &mut self.0 {
51            Inner::Unencoded(v) => v,
52            _ => unreachable!(),
53        }
54    }
55}
56
57impl<T, U> EncodeAs<T, U> {
58    /// Extracts the inner `T`.
59    pub fn into_inner(self) -> T {
60        match self.0 {
61            Inner::Unencoded(t) => t,
62            _ => unreachable!(),
63        }
64    }
65}
66
67impl<T, U: From<T>> EncodeAs<T, U> {
68    /// Constructs a new `EncodeAs` wrapping `t`.
69    pub fn new(t: T) -> Self {
70        Self(Inner::Unencoded(t))
71    }
72
73    fn encode(&mut self) -> &mut U {
74        match core::mem::replace(&mut self.0, Inner::Invalid) {
75            Inner::Unencoded(t) => {
76                self.0 = Inner::Encoded(t.into());
77            }
78            _ => unreachable!("already encoded"),
79        }
80        match &mut self.0 {
81            Inner::Encoded(u) => u,
82            _ => unreachable!(),
83        }
84    }
85}
86
87impl<T, U: From<T>> From<T> for EncodeAs<T, U> {
88    fn from(t: T) -> Self {
89        Self::new(t)
90    }
91}
92
93impl<T: Clone, U> Clone for EncodeAs<T, U> {
94    fn clone(&self) -> Self {
95        match &self.0 {
96            Inner::Unencoded(v) => Self(Inner::Unencoded(v.clone())),
97            _ => unreachable!(),
98        }
99    }
100}
101
102impl<T: Copy, U: Copy> Copy for EncodeAs<T, U> {}
103
104impl<T: Default, U> Default for Inner<T, U> {
105    fn default() -> Self {
106        Inner::Unencoded(Default::default())
107    }
108}
109
110impl<T: fmt::Display, U> fmt::Display for EncodeAs<T, U> {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        fmt::Display::fmt(self.deref(), f)
113    }
114}
115
116impl<T: fmt::Debug, U> fmt::Debug for EncodeAs<T, U> {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        fmt::Debug::fmt(self.deref(), f)
119    }
120}
121
122impl<T, U: From<T>, R, E: MessageEncode<U, R>> MessageEncode<EncodeAs<T, U>, R>
123    for EncodedMessage<E>
124{
125    fn write_message(item: EncodeAs<T, U>, writer: MessageWriter<'_, '_, R>) {
126        match item.0 {
127            Inner::Encoded(err) => E::write_message(err, writer),
128            _ => unreachable!("compute_message_size has not been called"),
129        }
130    }
131
132    fn compute_message_size(item: &mut EncodeAs<T, U>, sizer: MessageSizer<'_>) {
133        E::compute_message_size(item.encode(), sizer);
134    }
135}
136
137impl<'a, T, U: From<T> + Into<T>, R, E: MessageDecode<'a, U, R>>
138    MessageDecode<'a, EncodeAs<T, U>, R> for EncodedMessage<E>
139{
140    fn read_message(
141        item: &mut InplaceOption<'_, EncodeAs<T, U>>,
142        reader: MessageReader<'a, '_, R>,
143    ) -> Result<()> {
144        let encoded = item.take().map(|v| v.into_inner().into());
145        inplace!(encoded);
146        E::read_message(&mut encoded, reader)?;
147        item.set(EncodeAs(Inner::Unencoded(
148            encoded.take().expect("should be constructed").into(),
149        )));
150        Ok(())
151    }
152}
153
154impl<T, U: From<T> + Into<T> + DefaultEncoding> DefaultEncoding for EncodeAs<T, U> {
155    type Encoding = MessageEncoding<EncodedMessage<U::Encoding>>;
156}