Skip to main content

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