ddshow_types/
operator_addr.rs

1//! The [`OperatorAddr`] type
2
3use crate::ids::{OperatorId, PortId};
4use core::{
5    convert::TryFrom,
6    fmt::{self, Debug, Display},
7    iter::{FromIterator, IntoIterator},
8    mem::ManuallyDrop,
9    ops::Deref,
10    slice,
11};
12use tinyvec::{ArrayVec, TinyVec};
13
14#[cfg(feature = "enable_abomonation")]
15use abomonation::Abomonation;
16#[cfg(feature = "enable_abomonation")]
17use std::io;
18
19#[cfg(feature = "serde")]
20use serde_dep::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
21
22#[cfg(feature = "rkyv")]
23use rkyv_dep::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
24
25// TODO: Change this to use `OperatorId` instead of `usize`
26#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
27#[cfg_attr(
28    feature = "serde",
29    derive(SerdeSerialize, SerdeDeserialize),
30    serde(crate = "serde_dep", transparent)
31)]
32#[cfg_attr(
33    feature = "rkyv",
34    derive(Archive, RkyvSerialize, RkyvDeserialize),
35    archive(crate = "rkyv_dep", repr(transparent)),
36    archive_attr(derive(bytecheck::CheckBytes))
37)]
38#[repr(transparent)]
39pub struct OperatorAddr {
40    addr: TinyVec<[OperatorId; 8]>,
41}
42
43impl OperatorAddr {
44    #[inline]
45    pub const fn new(addr: TinyVec<[OperatorId; 8]>) -> Self {
46        Self { addr }
47    }
48
49    #[inline]
50    pub fn from_elem(segment: OperatorId) -> Self {
51        let zero = OperatorId::new(0);
52
53        Self::new(TinyVec::Inline(ArrayVec::from_array_len(
54            [segment, zero, zero, zero, zero, zero, zero, zero],
55            1,
56        )))
57    }
58
59    #[inline]
60    fn from_vec(addr: Vec<OperatorId>) -> Self {
61        let tiny_vec = ArrayVec::try_from(addr.as_slice())
62            .map_or_else(|_| TinyVec::Heap(addr), TinyVec::Inline);
63
64        Self::new(tiny_vec)
65    }
66
67    #[inline]
68    pub fn from_slice(addr: &[OperatorId]) -> Self {
69        let tiny_vec =
70            ArrayVec::try_from(addr).map_or_else(|_| TinyVec::Heap(addr.to_vec()), TinyVec::Inline);
71
72        Self::new(tiny_vec)
73    }
74
75    #[inline]
76    pub fn is_top_level(&self) -> bool {
77        self.len() == 1
78    }
79
80    #[inline]
81    pub fn push(&mut self, segment: PortId) {
82        self.addr.push(OperatorId::new(segment.into_inner()));
83    }
84
85    #[inline]
86    pub fn push_imm(&self, elem: PortId) -> Self {
87        let mut this = self.clone();
88        this.push(elem);
89        this
90    }
91
92    #[inline]
93    pub fn pop(&mut self) -> Option<OperatorId> {
94        self.addr.pop()
95    }
96
97    #[inline]
98    pub fn pop_imm(&self) -> (Self, Option<OperatorId>) {
99        let mut this = self.clone();
100        let popped = this.pop();
101
102        (this, popped)
103    }
104
105    #[inline]
106    pub fn as_slice(&self) -> &[OperatorId] {
107        self.addr.as_slice()
108    }
109
110    #[inline]
111    pub fn iter(&self) -> slice::Iter<'_, OperatorId> {
112        self.as_slice().iter()
113    }
114}
115
116impl From<&[OperatorId]> for OperatorAddr {
117    #[inline]
118    fn from(addr: &[OperatorId]) -> Self {
119        Self::from_slice(addr)
120    }
121}
122
123impl From<&Vec<OperatorId>> for OperatorAddr {
124    #[inline]
125    fn from(addr: &Vec<OperatorId>) -> Self {
126        Self::from_slice(addr)
127    }
128}
129
130impl From<Vec<OperatorId>> for OperatorAddr {
131    #[inline]
132    fn from(addr: Vec<OperatorId>) -> Self {
133        Self::from_vec(addr)
134    }
135}
136
137impl From<Vec<usize>> for OperatorAddr {
138    #[inline]
139    fn from(addr: Vec<usize>) -> Self {
140        // FIXME: Use `Vec::into_raw_parts()` once that's stable
141        // FIXME: Use `Vec::into_raw_parts_with_alloc()` once that's stable
142        let addr: Vec<OperatorId> = {
143            let mut addr = ManuallyDrop::new(addr);
144            let (ptr, len, cap) = (addr.as_mut_ptr().cast(), addr.len(), addr.capacity());
145
146            // Safety: `OperatorId` is a transparent wrapper around `usize`
147            unsafe { Vec::from_raw_parts(ptr, len, cap) }
148        };
149
150        let tiny_vec = ArrayVec::try_from(addr.as_slice())
151            .map_or_else(|_| TinyVec::Heap(addr), TinyVec::Inline);
152
153        Self::new(tiny_vec)
154    }
155}
156
157impl Deref for OperatorAddr {
158    type Target = [OperatorId];
159
160    #[inline]
161    fn deref(&self) -> &Self::Target {
162        &self.addr
163    }
164}
165
166impl Extend<OperatorId> for OperatorAddr {
167    #[inline]
168    fn extend<T>(&mut self, segments: T)
169    where
170        T: IntoIterator<Item = OperatorId>,
171    {
172        self.addr.extend(segments);
173    }
174}
175
176impl<'a> Extend<&'a OperatorId> for OperatorAddr {
177    #[inline]
178    fn extend<T>(&mut self, segments: T)
179    where
180        T: IntoIterator<Item = &'a OperatorId>,
181    {
182        self.addr.extend(segments.into_iter().copied());
183    }
184}
185
186impl FromIterator<OperatorId> for OperatorAddr {
187    #[inline]
188    fn from_iter<T: IntoIterator<Item = OperatorId>>(iter: T) -> Self {
189        Self {
190            addr: <TinyVec<[OperatorId; 8]>>::from_iter(iter),
191        }
192    }
193}
194
195impl<'a> FromIterator<&'a OperatorId> for OperatorAddr {
196    #[inline]
197    fn from_iter<T: IntoIterator<Item = &'a OperatorId>>(iter: T) -> Self {
198        Self {
199            addr: iter.into_iter().copied().collect(),
200        }
201    }
202}
203
204impl Debug for OperatorAddr {
205    #[inline]
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        // We can forward to our display implementation
208        Display::fmt(self, f)
209    }
210}
211
212impl Display for OperatorAddr {
213    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214        f.debug_list()
215            // FIXME: Is there really no way to make `.debug_list()`
216            //        call `Display` on elements?
217            .entries(self.as_slice().iter().copied().map(OperatorId::into_inner))
218            .finish()
219    }
220}
221
222#[cfg(feature = "enable_abomonation")]
223impl Abomonation for OperatorAddr {
224    #[inline]
225    unsafe fn entomb<W: io::Write>(&self, write: &mut W) -> io::Result<()> {
226        match &self.addr {
227            TinyVec::Inline(array) => array.into_inner().entomb(write),
228            TinyVec::Heap(vec) => vec.entomb(write),
229        }
230    }
231
232    #[inline]
233    unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
234        let mut inner = Vec::new();
235        let output = Vec::exhume(&mut inner, bytes)?;
236        self.addr = TinyVec::Heap(inner);
237
238        Some(output)
239    }
240
241    #[inline]
242    fn extent(&self) -> usize {
243        match &self.addr {
244            TinyVec::Inline(array) => array.into_inner().extent(),
245            TinyVec::Heap(vec) => vec.extent(),
246        }
247    }
248}