ergot_base/socket/
owned.rs

1//! "Owned" sockets
2//!
3//! "Owned" sockets require `T: 'static`, and store messages in their deserialized `T` form,
4//! rather as serialized bytes.
5//!
6//! This module contains versions of the [`raw_owned`](crate::socket::raw_owned) socket types
7//! that use a specific kind of storage.
8//!
9//! Currently we support:
10//!
11//! * `single` sockets, which use an `Option<T>` for storage, suitable for one-shot responses
12//! * `stack_vec` sockets, which use a heapless `Deque` for storage, and have a const-generic
13//!   size bound
14//! * `std_bounded` socket, which use a `std` `VecDeque` with an upper limit on the capacity
15
16macro_rules! wrapper {
17    ($sto: ty, $($arr: ident)?) => {
18        #[repr(transparent)]
19        pub struct Socket<T, NS, $(const $arr: usize)?>
20        where
21            T: Clone + serde::de::DeserializeOwned + 'static,
22            NS: $crate::net_stack::NetStackHandle,
23        {
24            socket: $crate::socket::raw_owned::Socket<$sto, T, NS>,
25        }
26
27        pub struct SocketHdl<'a, T, NS, $(const $arr: usize)?>
28        where
29            T: Clone + serde::de::DeserializeOwned + 'static,
30            NS: $crate::net_stack::NetStackHandle,
31        {
32            hdl: $crate::socket::raw_owned::SocketHdl<'a, $sto, T, NS>,
33        }
34
35        pub struct Recv<'a, 'b, T, NS, $(const $arr: usize)?>
36        where
37            T: Clone + serde::de::DeserializeOwned + 'static,
38            NS: $crate::net_stack::NetStackHandle,
39        {
40            recv: $crate::socket::raw_owned::Recv<'a, 'b, $sto, T, NS>,
41        }
42
43        impl<T, NS, $(const $arr: usize)?> Socket<T, NS, $($arr)?>
44        where
45            T: Clone + serde::de::DeserializeOwned + 'static,
46            NS: $crate::net_stack::NetStackHandle,
47        {
48            pub fn attach<'a>(self: core::pin::Pin<&'a mut Self>) -> SocketHdl<'a, T, NS, $($arr)?> {
49                let socket: core::pin::Pin<&'a mut $crate::socket::raw_owned::Socket<$sto, T, NS>>
50                    = unsafe { self.map_unchecked_mut(|me| &mut me.socket) };
51                SocketHdl {
52                    hdl: socket.attach(),
53                }
54            }
55
56            pub fn attach_broadcast<'a>(
57                self: core::pin::Pin<&'a mut Self>,
58            ) -> SocketHdl<'a, T, NS, $($arr)?> {
59                let socket: core::pin::Pin<&'a mut $crate::socket::raw_owned::Socket<$sto, T, NS>>
60                    = unsafe { self.map_unchecked_mut(|me| &mut me.socket) };
61                SocketHdl {
62                    hdl: socket.attach_broadcast(),
63                }
64            }
65
66            pub fn stack(&self) -> NS::Target {
67                self.socket.stack()
68            }
69        }
70
71        impl<'a, T, NS, $(const $arr: usize)?> SocketHdl<'a, T, NS, $($arr)?>
72        where
73            T: Clone + serde::de::DeserializeOwned + 'static,
74            NS: $crate::net_stack::NetStackHandle,
75        {
76            pub fn port(&self) -> u8 {
77                self.hdl.port()
78            }
79
80            pub fn stack(&self) -> NS::Target {
81                self.hdl.stack()
82            }
83
84            pub fn recv<'b>(&'b mut self) -> Recv<'b, 'a, T, NS, $($arr)?> {
85                Recv {
86                    recv: self.hdl.recv(),
87                }
88            }
89        }
90
91        impl<T, NS, $(const $arr: usize)?> Future for Recv<'_, '_, T, NS, $($arr)?>
92        where
93            T: Clone + serde::de::DeserializeOwned + 'static,
94            NS: $crate::net_stack::NetStackHandle,
95        {
96            type Output = $crate::socket::Response<T>;
97
98            fn poll(
99                self: core::pin::Pin<&mut Self>,
100                cx: &mut core::task::Context<'_>,
101            ) -> core::task::Poll<Self::Output> {
102                let recv: core::pin::Pin<&mut $crate::socket::raw_owned::Recv<'_, '_, $sto, T, NS>>
103                    = unsafe { self.map_unchecked_mut(|me| &mut me.recv) };
104                recv.poll(cx)
105            }
106        }
107    };
108}
109
110pub mod single {
111    use serde::de::DeserializeOwned;
112
113    use crate::{
114        Key,
115        net_stack::NetStackHandle,
116        socket::{Attributes, raw_owned},
117    };
118
119    impl<T: 'static> raw_owned::Storage<T> for Option<T> {
120        #[inline]
121        fn is_full(&self) -> bool {
122            self.is_some()
123        }
124
125        #[inline]
126        fn is_empty(&self) -> bool {
127            self.is_none()
128        }
129
130        #[inline]
131        fn push(&mut self, t: T) -> Result<(), raw_owned::StorageFull> {
132            if self.is_some() {
133                return Err(raw_owned::StorageFull);
134            }
135            *self = Some(t);
136            Ok(())
137        }
138
139        #[inline]
140        fn try_pop(&mut self) -> Option<T> {
141            self.take()
142        }
143    }
144
145    wrapper!(Option<crate::socket::Response<T>>,);
146
147    impl<T, NS> Socket<T, NS>
148    where
149        T: Clone + DeserializeOwned + 'static,
150        NS: NetStackHandle,
151    {
152        #[inline]
153        pub const fn new(net: NS::Target, key: Key, attrs: Attributes, name: Option<&str>) -> Self {
154            Self {
155                socket: raw_owned::Socket::new(net, key, attrs, None, name),
156            }
157        }
158    }
159}
160
161#[cfg(feature = "std")]
162pub mod std_bounded {
163    use serde::de::DeserializeOwned;
164    use std::collections::VecDeque;
165
166    use crate::{
167        Key,
168        net_stack::NetStackHandle,
169        socket::{Attributes, raw_owned},
170    };
171
172    pub struct Bounded<T> {
173        storage: std::collections::VecDeque<T>,
174        max_len: usize,
175    }
176
177    impl<T> Bounded<T> {
178        pub fn with_bound(bound: usize) -> Self {
179            Self {
180                storage: VecDeque::new(),
181                max_len: bound,
182            }
183        }
184    }
185
186    impl<T: 'static> raw_owned::Storage<T> for Bounded<T> {
187        #[inline]
188        fn is_full(&self) -> bool {
189            self.storage.len() >= self.max_len
190        }
191
192        #[inline]
193        fn is_empty(&self) -> bool {
194            self.storage.is_empty()
195        }
196
197        #[inline]
198        fn push(&mut self, t: T) -> Result<(), raw_owned::StorageFull> {
199            if self.is_full() {
200                return Err(raw_owned::StorageFull);
201            }
202            self.storage.push_back(t);
203            Ok(())
204        }
205
206        #[inline]
207        fn try_pop(&mut self) -> Option<T> {
208            self.storage.pop_front()
209        }
210    }
211
212    wrapper!(Bounded<crate::socket::Response<T>>,);
213
214    impl<T, NS> Socket<T, NS>
215    where
216        T: Clone + DeserializeOwned + 'static,
217        NS: NetStackHandle,
218    {
219        #[inline]
220        pub fn new(
221            net: NS::Target,
222            key: Key,
223            attrs: Attributes,
224            bound: usize,
225            name: Option<&str>,
226        ) -> Self {
227            Self {
228                socket: raw_owned::Socket::new(net, key, attrs, Bounded::with_bound(bound), name),
229            }
230        }
231    }
232}
233
234pub mod stack_vec {
235    use serde::de::DeserializeOwned;
236
237    use crate::Key;
238    use crate::net_stack::NetStackHandle;
239
240    use crate::socket::{Attributes, raw_owned};
241
242    pub struct Bounded<T: 'static, const N: usize> {
243        storage: heapless::Deque<T, N>,
244    }
245
246    impl<T: 'static, const N: usize> Bounded<T, N> {
247        pub const fn new() -> Self {
248            Self {
249                storage: heapless::Deque::new(),
250            }
251        }
252    }
253
254    impl<T: 'static, const N: usize> Default for Bounded<T, N> {
255        fn default() -> Self {
256            Self::new()
257        }
258    }
259
260    impl<T: 'static, const N: usize> raw_owned::Storage<T> for Bounded<T, N> {
261        #[inline]
262        fn is_full(&self) -> bool {
263            self.storage.is_full()
264        }
265
266        #[inline]
267        fn is_empty(&self) -> bool {
268            self.storage.is_empty()
269        }
270
271        #[inline]
272        fn push(&mut self, t: T) -> Result<(), raw_owned::StorageFull> {
273            self.storage
274                .push_back(t)
275                .map_err(|_| raw_owned::StorageFull)
276        }
277
278        #[inline]
279        fn try_pop(&mut self) -> Option<T> {
280            self.storage.pop_front()
281        }
282    }
283
284    wrapper!(Bounded<crate::socket::Response<T>, N>, N);
285
286    impl<T, NS, const N: usize> Socket<T, NS, N>
287    where
288        T: Clone + DeserializeOwned + 'static,
289        NS: NetStackHandle,
290    {
291        #[inline]
292        pub const fn new(net: NS::Target, key: Key, attrs: Attributes, name: Option<&str>) -> Self {
293            Self {
294                socket: raw_owned::Socket::new(net, key, attrs, Bounded::new(), name),
295            }
296        }
297    }
298}