stun_types/
data.rs

1// Copyright (C) 2020 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Data handling
10//!
11//! Provides a CoW interface for slices of `[u8]` and `Box<[u8]>`
12
13use alloc::boxed::Box;
14
15/// A slice of data
16#[derive(Debug, Clone, PartialEq, Eq)]
17#[repr(transparent)]
18pub struct DataSlice<'a>(&'a [u8]);
19
20impl<'a> DataSlice<'a> {
21    /// Consume this slice and return the underlying data.
22    pub fn take(self) -> &'a [u8] {
23        self.0
24    }
25
26    /// Copy this borrowed slice into a new owned allocation.
27    pub fn to_owned(&self) -> DataOwned {
28        DataOwned(self.0.into())
29    }
30}
31
32impl core::ops::Deref for DataSlice<'_> {
33    type Target = [u8];
34    fn deref(&self) -> &Self::Target {
35        self.0
36    }
37}
38
39impl<'a> From<DataSlice<'a>> for &'a [u8] {
40    fn from(value: DataSlice<'a>) -> Self {
41        value.0
42    }
43}
44
45impl<'a> From<&'a [u8]> for DataSlice<'a> {
46    fn from(value: &'a [u8]) -> Self {
47        Self(value)
48    }
49}
50
51/// An owned piece of data
52#[derive(Debug, Clone, PartialEq, Eq)]
53#[repr(transparent)]
54pub struct DataOwned(Box<[u8]>);
55
56impl DataOwned {
57    /// Consume this slice and return the underlying data.
58    pub fn take(self) -> Box<[u8]> {
59        self.0
60    }
61}
62
63impl core::ops::Deref for DataOwned {
64    type Target = [u8];
65    fn deref(&self) -> &Self::Target {
66        &self.0
67    }
68}
69
70impl From<DataOwned> for Box<[u8]> {
71    fn from(value: DataOwned) -> Self {
72        value.0
73    }
74}
75
76impl From<Box<[u8]>> for DataOwned {
77    fn from(value: Box<[u8]>) -> Self {
78        Self(value)
79    }
80}
81
82/// An owned or borrowed piece of data
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub enum Data<'a> {
85    /// Borrowed data.
86    Borrowed(DataSlice<'a>),
87    /// Owned data.
88    Owned(DataOwned),
89}
90
91impl core::ops::Deref for Data<'_> {
92    type Target = [u8];
93    fn deref(&self) -> &Self::Target {
94        match self {
95            Self::Borrowed(data) => data.0,
96            Self::Owned(data) => &data.0,
97        }
98    }
99}
100
101impl Data<'_> {
102    /// Create a new owned version of this data
103    pub fn into_owned<'b>(self) -> Data<'b> {
104        match self {
105            Self::Borrowed(data) => Data::Owned(data.to_owned()),
106            Self::Owned(data) => Data::Owned(data),
107        }
108    }
109}
110
111impl<'a> From<&'a [u8]> for Data<'a> {
112    fn from(value: &'a [u8]) -> Self {
113        Self::Borrowed(value.into())
114    }
115}
116
117impl From<Box<[u8]>> for Data<'_> {
118    fn from(value: Box<[u8]>) -> Self {
119        Self::Owned(value.into())
120    }
121}
122
123impl AsRef<[u8]> for Data<'_> {
124    fn as_ref(&self) -> &[u8] {
125        self
126    }
127}
128
129#[cfg(test)]
130pub(crate) mod tests {
131    use super::*;
132
133    #[test]
134    fn data_access() {
135        let _log = crate::tests::test_init_log();
136        let array = [0, 1, 2, 3];
137        let borrowed_data = Data::from(array.as_slice());
138        assert_eq!(array.as_slice(), &*borrowed_data);
139        let owned_data = borrowed_data.into_owned();
140        assert_eq!(array.as_slice(), &*owned_data);
141        let Data::Owned(owned) = owned_data else {
142            unreachable!();
143        };
144        let inner = <Box<[u8]>>::from(owned.clone());
145        assert_eq!(array.as_slice(), &*inner);
146        let owned = DataOwned::take(owned);
147        assert_eq!(array.as_slice(), &*owned);
148        let data = Data::from(owned);
149        assert_eq!(array.as_slice(), &*data);
150        let borrowed = DataSlice::from(&*data);
151        assert_eq!(array.as_slice(), &*borrowed);
152        let inner = <&[u8]>::from(borrowed.clone());
153        assert_eq!(array.as_slice(), inner);
154        let inner = borrowed.take();
155        assert_eq!(array.as_slice(), inner);
156    }
157}