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
13/// A slice of data
14#[derive(Debug, Clone, PartialEq, Eq)]
15#[repr(transparent)]
16pub struct DataSlice<'a>(&'a [u8]);
17
18impl<'a> DataSlice<'a> {
19    /// Consume this slice and return the underlying data.
20    pub fn take(self) -> &'a [u8] {
21        self.0
22    }
23
24    /// Copy this borrowed slice into a new owned allocation.
25    pub fn to_owned(&self) -> DataOwned {
26        DataOwned(self.0.into())
27    }
28}
29
30impl std::ops::Deref for DataSlice<'_> {
31    type Target = [u8];
32    fn deref(&self) -> &Self::Target {
33        self.0
34    }
35}
36
37impl<'a> From<DataSlice<'a>> for &'a [u8] {
38    fn from(value: DataSlice<'a>) -> Self {
39        value.0
40    }
41}
42
43impl<'a> From<&'a [u8]> for DataSlice<'a> {
44    fn from(value: &'a [u8]) -> Self {
45        Self(value)
46    }
47}
48
49/// An owned piece of data
50#[derive(Debug, Clone, PartialEq, Eq)]
51#[repr(transparent)]
52pub struct DataOwned(Box<[u8]>);
53
54impl DataOwned {
55    /// Consume this slice and return the underlying data.
56    pub fn take(self) -> Box<[u8]> {
57        self.0
58    }
59}
60
61impl std::ops::Deref for DataOwned {
62    type Target = [u8];
63    fn deref(&self) -> &Self::Target {
64        &self.0
65    }
66}
67
68impl From<DataOwned> for Box<[u8]> {
69    fn from(value: DataOwned) -> Self {
70        value.0
71    }
72}
73
74impl From<Box<[u8]>> for DataOwned {
75    fn from(value: Box<[u8]>) -> Self {
76        Self(value)
77    }
78}
79
80/// An owned or borrowed piece of data
81#[derive(Debug, Clone, PartialEq, Eq)]
82pub enum Data<'a> {
83    /// Borrowed data.
84    Borrowed(DataSlice<'a>),
85    /// Owned data.
86    Owned(DataOwned),
87}
88
89impl std::ops::Deref for Data<'_> {
90    type Target = [u8];
91    fn deref(&self) -> &Self::Target {
92        match self {
93            Self::Borrowed(data) => data.0,
94            Self::Owned(data) => &data.0,
95        }
96    }
97}
98
99impl Data<'_> {
100    /// Create a new owned version of this data
101    pub fn into_owned<'b>(self) -> Data<'b> {
102        match self {
103            Self::Borrowed(data) => Data::Owned(data.to_owned()),
104            Self::Owned(data) => Data::Owned(data),
105        }
106    }
107}
108
109impl<'a> From<&'a [u8]> for Data<'a> {
110    fn from(value: &'a [u8]) -> Self {
111        Self::Borrowed(value.into())
112    }
113}
114
115impl From<Box<[u8]>> for Data<'_> {
116    fn from(value: Box<[u8]>) -> Self {
117        Self::Owned(value.into())
118    }
119}
120
121impl AsRef<[u8]> for Data<'_> {
122    fn as_ref(&self) -> &[u8] {
123        self
124    }
125}
126
127#[cfg(test)]
128pub(crate) mod tests {
129    use super::*;
130
131    #[test]
132    fn data_access() {
133        let _log = crate::tests::test_init_log();
134        let array = [0, 1, 2, 3];
135        let borrowed_data = Data::from(array.as_slice());
136        assert_eq!(array.as_slice(), &*borrowed_data);
137        let owned_data = borrowed_data.into_owned();
138        assert_eq!(array.as_slice(), &*owned_data);
139        let Data::Owned(owned) = owned_data else {
140            unreachable!();
141        };
142        let inner = <Box<[u8]>>::from(owned.clone());
143        assert_eq!(array.as_slice(), &*inner);
144        let owned = DataOwned::take(owned);
145        assert_eq!(array.as_slice(), &*owned);
146        let data = Data::from(owned);
147        assert_eq!(array.as_slice(), &*data);
148        let borrowed = DataSlice::from(&*data);
149        assert_eq!(array.as_slice(), &*borrowed);
150        let inner = <&[u8]>::from(borrowed.clone());
151        assert_eq!(array.as_slice(), inner);
152        let inner = borrowed.take();
153        assert_eq!(array.as_slice(), inner);
154    }
155}