linux_perf_event_reader/
raw_data.rs

1use crate::utils::HexValue;
2use byteorder::{ByteOrder, NativeEndian};
3use std::borrow::Cow;
4use std::cmp::min;
5use std::ops::Range;
6use std::{fmt, mem};
7
8/// A slice of u8 data that can have non-contiguous backing storage split
9/// into two pieces, and abstracts that split away so that users can pretend
10/// to deal with a contiguous slice.
11///
12/// When reading perf events from the mmap'd fd that contains the perf event
13/// stream, it often happens that a single record straddles the boundary between
14/// two mmap chunks, or is wrapped from the end to the start of a chunk.
15#[derive(Clone, Copy, PartialEq, Eq)]
16pub enum RawData<'a> {
17    Single(&'a [u8]),
18    Split(&'a [u8], &'a [u8]),
19}
20
21impl<'a> From<&'a Cow<'a, [u8]>> for RawData<'a> {
22    fn from(data: &'a Cow<'a, [u8]>) -> Self {
23        match *data {
24            Cow::Owned(ref bytes) => RawData::Single(bytes.as_slice()),
25            Cow::Borrowed(bytes) => RawData::Single(bytes),
26        }
27    }
28}
29
30impl<'a> From<&'a [u8]> for RawData<'a> {
31    fn from(bytes: &'a [u8]) -> Self {
32        RawData::Single(bytes)
33    }
34}
35
36/// A helper which prints out byte slices but limits the output to 20 elements.
37struct DisplayableSlice<'a>(&'a [u8]);
38
39impl fmt::Display for DisplayableSlice<'_> {
40    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
41        let len = self.0.len();
42        if len == 0 {
43            return fmt.write_str("[]");
44        }
45
46        const MAX_PRINT_COUNT: usize = 20;
47        let need_ellipsis = len > MAX_PRINT_COUNT;
48        let print_count = len.min(MAX_PRINT_COUNT);
49        let last_printed_index = print_count - 1;
50
51        fmt.write_str("[")?;
52        for b in self.0.iter().take(last_printed_index) {
53            write!(fmt, "{b}, ")?;
54        }
55        write!(fmt, "{}", self.0[last_printed_index])?;
56        if need_ellipsis {
57            write!(
58                fmt,
59                ", ... (and {} more, total length {})",
60                len - MAX_PRINT_COUNT,
61                len
62            )?;
63        }
64        fmt.write_str("]")?;
65        Ok(())
66    }
67}
68
69impl fmt::Debug for RawData<'_> {
70    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
71        match *self {
72            RawData::Single(buffer) => {
73                write!(fmt, "RawData::Single({})", &DisplayableSlice(buffer))
74            }
75            RawData::Split(left, right) => write!(
76                fmt,
77                "RawData::Split({}, {})",
78                &DisplayableSlice(left),
79                &DisplayableSlice(right),
80            ),
81        }
82    }
83}
84
85impl<'a> RawData<'a> {
86    #[inline]
87    pub fn empty() -> Self {
88        RawData::Single(&[])
89    }
90
91    pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), std::io::Error> {
92        let buf_len = buf.len();
93        *self = match *self {
94            RawData::Single(single) => {
95                if single.len() < buf_len {
96                    return Err(std::io::ErrorKind::UnexpectedEof.into());
97                }
98                buf.copy_from_slice(&single[..buf_len]);
99                RawData::Single(&single[buf_len..])
100            }
101            RawData::Split(left, right) => {
102                let left_len = left.len();
103                if buf_len <= left_len {
104                    buf.copy_from_slice(&left[..buf_len]);
105                    if buf_len < left_len {
106                        RawData::Split(&left[buf_len..], right)
107                    } else {
108                        RawData::Single(right)
109                    }
110                } else {
111                    let remainder_len = buf_len - left_len;
112                    if remainder_len > right.len() {
113                        return Err(std::io::ErrorKind::UnexpectedEof.into());
114                    }
115                    buf[..left_len].copy_from_slice(left);
116                    buf[left_len..].copy_from_slice(&right[..remainder_len]);
117                    RawData::Single(&right[remainder_len..])
118                }
119            }
120        };
121        Ok(())
122    }
123
124    pub fn read_u64<T: ByteOrder>(&mut self) -> Result<u64, std::io::Error> {
125        let mut b = [0; 8];
126        self.read_exact(&mut b)?;
127        Ok(T::read_u64(&b))
128    }
129
130    pub fn read_u32<T: ByteOrder>(&mut self) -> Result<u32, std::io::Error> {
131        let mut b = [0; 4];
132        self.read_exact(&mut b)?;
133        Ok(T::read_u32(&b))
134    }
135
136    pub fn read_i32<T: ByteOrder>(&mut self) -> Result<i32, std::io::Error> {
137        let mut b = [0; 4];
138        self.read_exact(&mut b)?;
139        Ok(T::read_i32(&b))
140    }
141
142    pub fn read_u16<T: ByteOrder>(&mut self) -> Result<u16, std::io::Error> {
143        let mut b = [0; 2];
144        self.read_exact(&mut b)?;
145        Ok(T::read_u16(&b))
146    }
147
148    pub fn read_u8(&mut self) -> Result<u8, std::io::Error> {
149        let mut b = [0; 1];
150        self.read_exact(&mut b)?;
151        Ok(b[0])
152    }
153
154    /// Finds the first nul byte. Returns everything before that nul byte.
155    /// Sets self to everything after the nul byte.
156    pub fn read_string(&mut self) -> Option<RawData<'a>> {
157        let (rv, new_self) = match *self {
158            RawData::Single(single) => {
159                let n = memchr::memchr(0, single)?;
160                (
161                    RawData::Single(&single[..n]),
162                    RawData::Single(&single[n + 1..]),
163                )
164            }
165            RawData::Split(left, right) => {
166                if let Some(n) = memchr::memchr(0, left) {
167                    (
168                        RawData::Single(&left[..n]),
169                        if n + 1 < left.len() {
170                            RawData::Split(&left[n + 1..], right)
171                        } else {
172                            RawData::Single(right)
173                        },
174                    )
175                } else if let Some(n) = memchr::memchr(0, right) {
176                    (
177                        RawData::Split(left, &right[..n]),
178                        RawData::Single(&right[n + 1..]),
179                    )
180                } else {
181                    return None;
182                }
183            }
184        };
185        *self = new_self;
186        Some(rv)
187    }
188
189    /// Returns the first `n` bytes, and sets self to the remainder.
190    pub fn split_off_prefix(&mut self, n: usize) -> Result<Self, std::io::Error> {
191        let (rv, new_self) = match *self {
192            RawData::Single(single) => {
193                if single.len() < n {
194                    return Err(std::io::ErrorKind::UnexpectedEof.into());
195                }
196                (RawData::Single(&single[..n]), RawData::Single(&single[n..]))
197            }
198            RawData::Split(left, right) => {
199                if n <= left.len() {
200                    (
201                        RawData::Single(&left[..n]),
202                        if n < left.len() {
203                            RawData::Split(&left[n..], right)
204                        } else {
205                            RawData::Single(right)
206                        },
207                    )
208                } else {
209                    let remainder_len = n - left.len();
210                    if remainder_len > right.len() {
211                        return Err(std::io::ErrorKind::UnexpectedEof.into());
212                    }
213                    (
214                        RawData::Split(left, &right[..remainder_len]),
215                        RawData::Single(&right[remainder_len..]),
216                    )
217                }
218            }
219        };
220        *self = new_self;
221        Ok(rv)
222    }
223
224    pub fn skip(&mut self, n: usize) -> Result<(), std::io::Error> {
225        *self = match *self {
226            RawData::Single(single) => {
227                if single.len() < n {
228                    return Err(std::io::ErrorKind::UnexpectedEof.into());
229                }
230                RawData::Single(&single[n..])
231            }
232            RawData::Split(left, right) => {
233                if n < left.len() {
234                    RawData::Split(&left[n..], right)
235                } else {
236                    let remainder_len = n - left.len();
237                    if remainder_len > right.len() {
238                        return Err(std::io::ErrorKind::UnexpectedEof.into());
239                    }
240                    RawData::Single(&right[remainder_len..])
241                }
242            }
243        };
244        Ok(())
245    }
246
247    #[inline]
248    fn write_into(&self, target: &mut Vec<u8>) {
249        target.clear();
250        match *self {
251            RawData::Single(slice) => target.extend_from_slice(slice),
252            RawData::Split(first, second) => {
253                target.reserve(first.len() + second.len());
254                target.extend_from_slice(first);
255                target.extend_from_slice(second);
256            }
257        }
258    }
259
260    pub fn as_slice(&self) -> Cow<'a, [u8]> {
261        match *self {
262            RawData::Single(buffer) => buffer.into(),
263            RawData::Split(..) => {
264                let mut vec = Vec::new();
265                self.write_into(&mut vec);
266                vec.into()
267            }
268        }
269    }
270
271    pub fn get(&self, range: Range<usize>) -> Option<RawData<'a>> {
272        Some(match self {
273            RawData::Single(buffer) => RawData::Single(buffer.get(range)?),
274            RawData::Split(left, right) => {
275                if range.start >= left.len() {
276                    RawData::Single(right.get(range.start - left.len()..range.end - left.len())?)
277                } else if range.end <= left.len() {
278                    RawData::Single(left.get(range)?)
279                } else {
280                    let left = left.get(range.start..)?;
281                    let right = right.get(..min(range.end - left.len(), right.len()))?;
282                    RawData::Split(left, right)
283                }
284            }
285        })
286    }
287
288    pub fn is_empty(&self) -> bool {
289        match *self {
290            RawData::Single(buffer) => buffer.is_empty(),
291            RawData::Split(left, right) => left.is_empty() && right.is_empty(),
292        }
293    }
294
295    pub fn len(&self) -> usize {
296        match *self {
297            RawData::Single(buffer) => buffer.len(),
298            RawData::Split(left, right) => left.len() + right.len(),
299        }
300    }
301}
302
303#[derive(Clone, Copy, PartialEq, Eq)]
304pub struct RawDataU64<'a> {
305    swapped_endian: bool,
306    raw_data: RawData<'a>,
307}
308
309pub fn is_swapped_endian<T: ByteOrder>() -> bool {
310    let mut buf = [0; 2];
311    T::write_u16(&mut buf, 0x1234);
312    u16::from_ne_bytes(buf) != 0x1234
313}
314
315impl<'a> RawDataU64<'a> {
316    #[inline]
317    pub fn from_raw_data<T: ByteOrder>(raw_data: RawData<'a>) -> Self {
318        RawDataU64 {
319            raw_data,
320            swapped_endian: is_swapped_endian::<T>(),
321        }
322    }
323
324    pub fn is_empty(&self) -> bool {
325        self.raw_data.is_empty()
326    }
327
328    pub fn len(&self) -> usize {
329        self.raw_data.len() / mem::size_of::<u64>()
330    }
331
332    pub fn get(&self, index: usize) -> Option<u64> {
333        let offset = index * mem::size_of::<u64>();
334        let mut data = self.raw_data;
335        data.skip(offset).ok()?;
336        let value = data.read_u64::<NativeEndian>().ok()?;
337        Some(if self.swapped_endian {
338            value.swap_bytes()
339        } else {
340            value
341        })
342    }
343}
344
345impl std::fmt::Debug for RawDataU64<'_> {
346    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
347        let mut list = fmt.debug_list();
348        let mut data = self.raw_data;
349        while let Ok(value) = data.read_u64::<NativeEndian>() {
350            let value = if self.swapped_endian {
351                value.swap_bytes()
352            } else {
353                value
354            };
355            list.entry(&HexValue(value));
356        }
357
358        list.finish()
359    }
360}
361
362#[cfg(test)]
363mod test {
364    use super::RawData;
365
366    #[test]
367    fn test_reading_from_split() {
368        let full = b"CDEF===AB"; // 0123___78"
369        assert_eq!(full.len(), 9);
370        let mut split = RawData::Split(&full[7..9], &full[0..4]);
371        let mut dest = vec![0; 6];
372        split.read_exact(&mut dest).unwrap();
373        assert_eq!(&dest, b"ABCDEF");
374    }
375}