tacacs_plus_protocol/
owned.rs

1use super::DeserializeError;
2use super::PacketType;
3use super::{sealed::Sealed, Deserialize, PacketBody};
4
5/// Converts a reference-based packet to a packet that owns its fields.
6///
7/// A [`Borrow`](std::borrow::Borrow) impl for the different packet types would be nontrivial, if even possible,
8/// which is why the [`ToOwned`](std::borrow::ToOwned) trait isn't used.
9///
10/// This is also a From-style trait due to a blanket impl for [`Deserialize`] that it is used for.
11pub trait FromBorrowedBody: Sealed {
12    /// The borrowed variant of this packet body.
13    type Borrowed<'b>: PacketBody;
14
15    /// Converts the borrowed variant of this packet body to its owned variant.
16    fn from_borrowed(borrowed: &Self::Borrowed<'_>) -> Self;
17}
18
19impl<'b, B: FromBorrowedBody> Deserialize<'b> for B
20where
21    B::Borrowed<'b>: Deserialize<'b>,
22{
23    fn deserialize_from_buffer(buffer: &'b [u8]) -> Result<Self, DeserializeError> {
24        let borrowed = <B as FromBorrowedBody>::Borrowed::deserialize_from_buffer(buffer)?;
25        Ok(Self::from_borrowed(&borrowed))
26    }
27}
28
29// boilerplate but necessary for above blanket Deserialize impl
30// NOTE: this also ignores the required_minor_version function which is irrelevant for every
31// packet type except authentication::Start, which doesn't have an owned variant as of now
32impl<B: FromBorrowedBody> PacketBody for B {
33    const TYPE: PacketType = <<B as FromBorrowedBody>::Borrowed<'_> as PacketBody>::TYPE;
34    const REQUIRED_FIELDS_LENGTH: usize =
35        <<B as FromBorrowedBody>::Borrowed<'_> as PacketBody>::REQUIRED_FIELDS_LENGTH;
36}