perf_event_data/
parse.rs

1//! Parsing interface for parsing data in to record types.
2//!
3//! In this crate, parsing is built on parser functions that take in a
4//! [`Parser`] and produce a [`Result<T>`] where `T` is some record type. Most
5//! of the time, you should be able to call [`Parser::parse`] for each of your
6//! fields but [`Parser`] provides many other helper methods for when that isn't
7//! enough.
8//!
9//! # Parsing a Record
10//! The quickest and easiest way to get started is to just parse everything to
11//! the [`Record`] type.
12//!
13//! ```
14//! # fn main() -> perf_event_data::parse::ParseResult<()> {
15//! use perf_event_data::endian::Little;
16//! use perf_event_data::parse::{ParseConfig, Parser};
17//! use perf_event_data::Record;
18//!
19//! let data: &[u8] = // ...
20//! #       perf_event_data::doctest::MMAP;
21//! let config = ParseConfig::<Little>::default();
22//! let mut parser = Parser::new(data, config);
23//! let record: Record = parser.parse()?;
24//! # Ok(())
25//! # }
26//! ```
27//!
28//! # Parsing Custom Types
29//! The types provided in this crate aim to cover all the possible types of
30//! record that can be emitted by `perf_event_open`. However, if you control the
31//! configuration passed to `perf_event_open` then the types in this crate can
32//! be overly general. You may find it easier to define custom types that match
33//! exactly the record types you know will be generated.
34//!
35//! To do that you will need to implement [`Parse`] for your type, use
36//! [`Parser::parse_metadata`] to parse the record frame, and then use
37//! [`Parser::parse`] to parse your custom record type.
38//!
39//! Here we define a sample type that only parses the custom fields we care
40//! about.
41//! ```
42//! # fn main() -> perf_event_data::parse::ParseResult<()> {
43//! use perf_event_data::endian::{Endian, Little};
44//! use perf_event_data::parse::{Parse, ParseBuf, ParseConfig, ParseResult, Parser};
45//! use perf_event_data::Registers;
46//! use perf_event_open_sys::bindings::PERF_RECORD_SAMPLE;
47//!
48//! struct CustomSample {
49//!     pub ip: u64,
50//!     pub pid: u32,
51//!     pub tid: u32,
52//!     pub callstack: Vec<u64>,
53//!     pub cgroup: u64,
54//! }
55//!
56//! impl<'p> Parse<'p> for CustomSample {
57//!     fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
58//!     where
59//!         B: ParseBuf<'p>,
60//!         E: Endian,
61//!     {
62//!         Ok(Self {
63//!             ip: p.parse()?,
64//!             pid: p.parse()?,
65//!             tid: p.parse()?,
66//!             callstack: {
67//!                 let len = p.parse_u64()?;
68//!                 p.parse_repeated(len as usize)?
69//!             },
70//!             cgroup: p.parse()?,
71//!         })
72//!     }
73//! }
74//!
75//! let data: &[u8] = // ...
76//! #   perf_event_data::doctest::CUSTOM_SAMPLE;
77//! let attr: perf_event_open_sys::bindings::perf_event_attr = // ...
78//! #   Default::default();
79//! let config: ParseConfig<Little> = ParseConfig::from(attr);
80//! let mut parser = Parser::new(data, config);
81//!
82//! let (mut p, metadata) = parser.parse_metadata()?;
83//!
84//! assert_eq!(metadata.ty(), PERF_RECORD_SAMPLE);
85//! let sample: CustomSample = p.parse()?;
86//! #
87//! # assert_eq!(metadata.misc(), 0);
88//! # assert_eq!(sample.ip, 0x3C2B1A9948331210, "ip did not match");
89//! # assert_eq!(sample.pid, 2);
90//! # assert_eq!(sample.tid, 3);
91//! # assert_eq!(sample.callstack.len(), 4);
92//! # assert_eq!(sample.cgroup, 0xC9406500006540C9, "gcroup did not match");
93//! #
94//! # Ok(())
95//! # }
96//! ```
97
98use std::borrow::Cow;
99use std::mem::MaybeUninit;
100
101use perf_event_open_sys::bindings;
102
103use crate::endian::Endian;
104use crate::parsebuf::{ParseBufCursor, TrackingParseBuf};
105use crate::util::cow::CowSliceExt;
106use crate::{Record, RecordMetadata, SampleId, Visitor};
107
108used_in_docs!(Record);
109
110pub use crate::config::ParseConfig;
111pub use crate::error::{ErrorKind, ParseError, ParseResult};
112pub use crate::parsebuf::{ParseBuf, ParseBufChunk};
113
114/// A type that can be parsed
115pub trait Parse<'p>: Sized {
116    /// Parse `Self` using the provided [`Parser`] instance.
117    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
118    where
119        E: Endian,
120        B: ParseBuf<'p>;
121}
122
123/// A [`ParseConfig`] combined with a [`ParseBuf`].
124///
125/// This type is the base on which all parsing in this library occurs. It has a
126/// number of helper methods that do common parsing operations needed when
127/// implementing [`Parse`] for a record type.
128///
129/// # Important Methods
130/// If you are using this library to parse an perf event stream emitted either
131/// by [`perf_event_open(2)`][0] or by parsing a `perf.data` file then likely
132/// want one of
133/// - [`parse_record`](Parser::parse_record), or,
134/// - [`parse_record_with_header`](Parser::parse_record_with_header)
135///
136/// If you are implementing [`Parse`] for a type then you will likely be using
137/// - [`parse`](Parser::parse), and,
138/// - [`parse_bytes`](Parser::parse_bytes)
139///
140/// Other methods are provided if they were needed but those should be the main
141/// ones.
142///
143/// [0]: https://man7.org/linux/man-pages/man2/perf_event_open.2.html
144#[derive(Clone)]
145pub struct Parser<B, E> {
146    config: ParseConfig<E>,
147    data: TrackingParseBuf<B>,
148}
149
150impl<'p, B, E> Parser<B, E>
151where
152    E: Endian,
153    B: ParseBuf<'p>,
154{
155    /// Create a new parser.
156    pub fn new(data: B, config: ParseConfig<E>) -> Self {
157        Self {
158            config,
159            data: TrackingParseBuf::new(data),
160        }
161    }
162
163    /// Get the [`ParseConfig`] instance for this `Parser`.
164    #[inline]
165    pub fn config(&self) -> &ParseConfig<E> {
166        &self.config
167    }
168
169    /// Get the endian configuration type.
170    #[inline]
171    pub fn endian(&self) -> &E {
172        self.config.endian()
173    }
174
175    /// Advance the current parser by `offset` and return a new parser for the
176    /// data within.
177    pub(crate) fn split_at(&mut self, offset: usize) -> ParseResult<Parser<ParseBufCursor<'p>, E>> {
178        let cursor = ParseBufCursor::new(&mut self.data, offset)?;
179        Ok(Parser::new(cursor, self.config().clone()))
180    }
181
182    /// Calculate a maximum capacity bound for a slice of `T`.
183    ///
184    /// This is to prevent unbounded memory allocation when parsing untrusted
185    /// input such as a file on disk. The goal is that if an input is going to
186    /// cause our program to run out of memory they must at least pass a
187    /// corresponding number of bytes which can be handled at a higher level.
188    fn safe_capacity_bound<T>(&self) -> usize {
189        const DEFAULT_LEN: usize = 16384;
190
191        let size = std::mem::size_of::<T>();
192        // No memory will be allocated, we are free to do whatever
193        if size == 0 {
194            return usize::MAX;
195        }
196
197        // Allow allocating at most as many elements as would fit in the buffer, or
198        // 16KB, whichever is larger. This should address cases where the size of T does
199        // not correspond to the number of bytes read from the buffer.
200        self.data.remaining_hint().unwrap_or(DEFAULT_LEN) / size
201    }
202
203    fn parse_bytes_direct(&mut self, len: usize) -> ParseResult<Option<&'p [u8]>> {
204        let chunk = match self.data.chunk()? {
205            ParseBufChunk::External(chunk) => chunk,
206            _ => return Ok(None),
207        };
208
209        if chunk.len() < len {
210            return Ok(None);
211        }
212
213        self.data.advance(len);
214        Ok(Some(&chunk[..len]))
215    }
216
217    /// Safe implementation for when we cannot preallocate the buffer.
218    #[cold]
219    fn parse_bytes_slow(&mut self, mut len: usize) -> ParseResult<Vec<u8>> {
220        let mut bytes = Vec::with_capacity(self.safe_capacity_bound::<u8>().min(len));
221
222        while len > 0 {
223            let mut chunk = self.data.chunk()?;
224            chunk.truncate(len);
225            bytes.extend_from_slice(&chunk);
226
227            let chunk_len = chunk.len();
228            len -= chunk_len;
229            self.data.advance(chunk_len);
230        }
231
232        Ok(bytes)
233    }
234
235    /// Directly get a reference to the next `len` bytes in the input buffer.
236    pub fn parse_bytes(&mut self, len: usize) -> ParseResult<Cow<'p, [u8]>> {
237        if let Some(bytes) = self.parse_bytes_direct(len)? {
238            return Ok(Cow::Borrowed(bytes));
239        }
240
241        match self.data.remaining_hint() {
242            Some(hint) if hint >= len => (),
243            _ => return Ok(Cow::Owned(self.parse_bytes_slow(len)?)),
244        }
245
246        let mut bytes = Vec::with_capacity(len);
247        self.parse_to_slice(bytes.spare_capacity_mut())?;
248        unsafe { bytes.set_len(len) };
249        Ok(Cow::Owned(bytes))
250    }
251
252    /// Advance the stream by a number of bytes (with checking) but ignore the
253    /// resulting bytes.
254    fn parse_bytes_ignored(&mut self, mut len: usize) -> ParseResult<()> {
255        while len > 0 {
256            let chunk = self.data.chunk()?;
257            let consumed = chunk.len().min(len);
258
259            len -= consumed;
260            self.data.advance(consumed);
261        }
262
263        Ok(())
264    }
265
266    /// Parse a slice in its entirety. If this returns successfully then the
267    /// entire slice has been initialized.
268    fn parse_to_slice(&mut self, slice: &mut [MaybeUninit<u8>]) -> ParseResult<()> {
269        let mut dst = slice.as_mut_ptr() as *mut u8;
270        let mut len = slice.len();
271
272        while len > 0 {
273            let chunk = self.data.chunk()?;
274            let chunk_len = chunk.len().min(len);
275
276            unsafe {
277                std::ptr::copy_nonoverlapping(chunk.as_ptr(), dst, chunk_len);
278                dst = dst.add(chunk_len);
279                len -= chunk_len;
280            };
281
282            self.data.advance(chunk_len);
283        }
284
285        Ok(())
286    }
287
288    #[cold]
289    fn parse_array_slow<const N: usize>(&mut self) -> ParseResult<[u8; N]> {
290        let mut array = [0u8; N];
291        self.parse_to_slice(unsafe { array.align_to_mut().1 })?;
292        Ok(array)
293    }
294
295    pub(crate) fn parse_array<const N: usize>(&mut self) -> ParseResult<[u8; N]> {
296        let chunk = self.data.chunk()?;
297
298        if chunk.len() < N {
299            return self.parse_array_slow();
300        }
301
302        let mut array = [0u8; N];
303        array.copy_from_slice(&chunk[..N]);
304        self.data.advance(N);
305        Ok(array)
306    }
307
308    /// Parse a type.
309    ///
310    /// If the type fails to parse then this parser will not be modified.
311    pub fn parse<P: Parse<'p>>(&mut self) -> ParseResult<P> {
312        P::parse(self)
313    }
314
315    /// Parse with an explicit parsing function.
316    pub fn parse_with<F, R>(&mut self, func: F) -> ParseResult<R>
317    where
318        F: FnOnce(&mut Self) -> ParseResult<R>,
319    {
320        func(self)
321    }
322
323    /// Parse a type only if `parse` is true.
324    pub fn parse_if<P: Parse<'p>>(&mut self, parse: bool) -> ParseResult<Option<P>> {
325        self.parse_if_with(parse, P::parse)
326    }
327
328    /// `parse_if` but using an explicit parsing function.
329    pub fn parse_if_with<F, R>(&mut self, parse: bool, func: F) -> ParseResult<Option<R>>
330    where
331        F: FnOnce(&mut Self) -> ParseResult<R>,
332    {
333        match parse {
334            true => self.parse_with(func).map(Some),
335            false => Ok(None),
336        }
337    }
338
339    /// Parse some input and advance the [`ParseBuf`] so a multiple of `padding`
340    /// bytes are consumed.
341    ///
342    /// This is a somewhat common need since fields in various perf event
343    /// structures are usually required to be 8-byte aligned.
344    ///
345    /// # Panics
346    /// Panics if `padding` is 0.
347    pub(crate) fn parse_padded<F, R>(&mut self, padding: usize, func: F) -> ParseResult<R>
348    where
349        F: FnOnce(&mut Self) -> ParseResult<R>,
350    {
351        assert_ne!(padding, 0);
352
353        let offset = self.data.offset();
354        let value = func(self)?;
355        let parsed = self.data.offset() - offset;
356
357        match parsed % padding {
358            // do nothing, we are already aligned
359            0 => (),
360            n => self.parse_bytes_ignored(padding - n)?,
361        }
362
363        Ok(value)
364    }
365
366    /// Parse a single byte out of the source buffer.
367    pub fn parse_u8(&mut self) -> ParseResult<u8> {
368        let [byte] = self.parse_array()?;
369        Ok(byte)
370    }
371
372    /// Parse a `u16` out of the source data.
373    pub fn parse_u16(&mut self) -> ParseResult<u16> {
374        let array = self.parse_array()?;
375        Ok(self.endian().convert_u16(array))
376    }
377
378    /// Parse a `u32` out of the source data.
379    pub fn parse_u32(&mut self) -> ParseResult<u32> {
380        let array = self.parse_array()?;
381        Ok(self.endian().convert_u32(array))
382    }
383
384    /// Parse a `u64` out of the source data.
385    pub fn parse_u64(&mut self) -> ParseResult<u64> {
386        let array = self.parse_array()?;
387        Ok(self.endian().convert_u64(array))
388    }
389
390    /// Consume the rest of the buffer and return it as a slice.
391    pub fn parse_rest(&mut self) -> ParseResult<Cow<'p, [u8]>> {
392        let mut bytes = self.data.chunk()?.to_cow();
393        self.data.advance(bytes.len());
394
395        loop {
396            match self.data.chunk() {
397                Ok(chunk) => {
398                    bytes.to_mut().extend_from_slice(&chunk);
399
400                    let len = chunk.len();
401                    self.data.advance(len);
402                }
403                Err(e) if e.kind() == ErrorKind::Eof => break,
404                Err(e) => return Err(e),
405            }
406        }
407
408        Ok(bytes)
409    }
410
411    /// Parse the rest of the bytes in the buffer but trim trailing nul bytes.
412    pub fn parse_rest_trim_nul(&mut self) -> ParseResult<Cow<'p, [u8]>> {
413        let mut bytes = self.parse_rest()?;
414
415        // Trim padding nul bytes from the entry.
416        let mut rest = &*bytes;
417        while let Some((b'\0', head)) = rest.split_last() {
418            rest = head;
419        }
420
421        bytes.truncate(rest.len());
422        Ok(bytes)
423    }
424
425    /// Attempt to directly transmute a slice in the source buffer to one of
426    /// type T.
427    ///
428    /// This method will only succeed if
429    /// 1. the source endianness is the same as the endianness of this program,
430    ///    and
431    /// 2. the buffer is properly aligned for `T`.
432    ///
433    /// This method is mainly meant to reduce copying when parsing the records
434    /// emitted directly from the kernel. If you are parsing from a buffer read
435    /// in from a file then it is unlikely that you will meet all the required
436    /// preconditions.
437    ///
438    /// # Safety
439    /// It must be valid to transmute `T` directly from bytes. The `Copy` bound
440    /// is a step towards ensuring this.
441    pub unsafe fn parse_slice_direct<T>(&mut self, len: usize) -> ParseResult<Option<&'p [T]>>
442    where
443        T: Copy,
444    {
445        // The current endianness is not native so reinterpreting as `T` would not be
446        // valid.
447        if !self.endian().is_native() {
448            return Ok(None);
449        }
450
451        let byte_len = len.checked_mul(std::mem::size_of::<T>()).ok_or_else(|| {
452            ParseError::custom(
453                ErrorKind::InvalidRecord,
454                "array length in bytes larger than usize::MAX",
455            )
456        })?;
457        let bytes = match self.parse_bytes_direct(byte_len)? {
458            Some(bytes) => bytes,
459            None => return Ok(None),
460        };
461        let (head, slice, tail) = bytes.align_to();
462
463        if !head.is_empty() || !tail.is_empty() {
464            return Ok(None);
465        }
466
467        Ok(Some(slice))
468    }
469
470    /// Attempt to directly transmute a slice in the source buffer and, if that
471    /// fails, parse it instead.
472    ///
473    /// # Safety
474    /// This has all the same safety preconditions as
475    /// [`parse_slice_direct`](Self::parse_slice_direct). That is, is must be
476    /// valid to transmute bytes in to a `T` instance.
477    pub unsafe fn parse_slice<T>(&mut self, len: usize) -> ParseResult<Cow<'p, [T]>>
478    where
479        T: Parse<'p> + Copy,
480    {
481        Ok(match self.parse_slice_direct(len)? {
482            Some(slice) => Cow::Borrowed(slice),
483            None => Cow::Owned(self.parse_repeated(len)?),
484        })
485    }
486
487    /// Parse a sequence of `len` `T`s.
488    pub fn parse_repeated<T: Parse<'p>>(&mut self, len: usize) -> ParseResult<Vec<T>> {
489        let mut vec = Vec::with_capacity(len.min(self.safe_capacity_bound::<T>()));
490        for _ in 0..len {
491            vec.push(self.parse()?);
492        }
493
494        Ok(vec)
495    }
496
497    /// Parse record metadata and return a parser for the bytes of the record.
498    ///
499    /// If you have already read the record header, use
500    /// [`parse_metadata_with_header`](Parser::parse_metadata_with_header)
501    /// instead.
502    pub fn parse_metadata(
503        &mut self,
504    ) -> ParseResult<(Parser<impl ParseBuf<'p>, E>, RecordMetadata)> {
505        let header = self.parse()?;
506        self.parse_metadata_with_header(header)
507    }
508
509    fn parse_metadata_with_header_impl(
510        &mut self,
511        header: bindings::perf_event_header,
512    ) -> ParseResult<(Parser<ParseBufCursor<'p>, E>, RecordMetadata)> {
513        use perf_event_open_sys::bindings::*;
514        use std::mem;
515
516        let data_len = (header.size as usize)
517            .checked_sub(mem::size_of_val(&header))
518            .ok_or_else(|| {
519                ParseError::custom(
520                    ErrorKind::InvalidRecord,
521                    "header size was too small to be valid",
522                )
523            })?;
524        let mut rp = self.split_at(data_len)?;
525        // MMAP and SAMPLE records do not have the sample_id struct.
526        // All other records do.
527        let (p, sample_id) = match header.type_ {
528            PERF_RECORD_MMAP | PERF_RECORD_SAMPLE => (rp, SampleId::default()),
529            _ => {
530                let remaining_len = data_len
531                    .checked_sub(SampleId::estimate_len(rp.config()))
532                    .ok_or_else(|| ParseError::custom(
533                        ErrorKind::InvalidRecord,
534                        "config has sample_id_all bit set but record does not have enough data to store the sample_id"
535                    ))?;
536
537                let p = rp.split_at(remaining_len)?;
538                (p, rp.parse()?)
539            }
540        };
541
542        let metadata = RecordMetadata::new(header, sample_id);
543        Ok((p, metadata))
544    }
545
546    /// Parse the record metadata and return a parser for only the record bytes.
547    pub fn parse_metadata_with_header(
548        &mut self,
549        header: bindings::perf_event_header,
550    ) -> ParseResult<(Parser<impl ParseBuf<'p>, E>, RecordMetadata)> {
551        self.parse_metadata_with_header_impl(header)
552    }
553
554    /// Parse a record, the record types will be visited by the `visitor`.
555    pub fn parse_record<V: Visitor<'p>>(&mut self, visitor: V) -> ParseResult<V::Output> {
556        let header = self.parse()?;
557        self.parse_record_with_header(visitor, header)
558    }
559
560    fn parse_record_impl<V: Visitor<'p>>(
561        self,
562        visitor: V,
563        metadata: RecordMetadata,
564    ) -> ParseResult<V::Output> {
565        use perf_event_open_sys::bindings::*;
566
567        let mut p = Parser::new(self.data, self.config.with_misc(metadata.misc()));
568
569        Ok(match metadata.ty() {
570            PERF_RECORD_MMAP => visitor.visit_mmap(p.parse()?, metadata),
571            PERF_RECORD_LOST => visitor.visit_lost(p.parse()?, metadata),
572            PERF_RECORD_COMM => visitor.visit_comm(p.parse()?, metadata),
573            PERF_RECORD_EXIT => visitor.visit_exit(p.parse()?, metadata),
574            PERF_RECORD_THROTTLE => visitor.visit_throttle(p.parse()?, metadata),
575            PERF_RECORD_UNTHROTTLE => visitor.visit_unthrottle(p.parse()?, metadata),
576            PERF_RECORD_FORK => visitor.visit_fork(p.parse()?, metadata),
577            PERF_RECORD_READ => visitor.visit_read(p.parse()?, metadata),
578            PERF_RECORD_SAMPLE => visitor.visit_sample(p.parse()?, metadata),
579            PERF_RECORD_MMAP2 => visitor.visit_mmap2(p.parse()?, metadata),
580            PERF_RECORD_AUX => visitor.visit_aux(p.parse()?, metadata),
581            PERF_RECORD_ITRACE_START => visitor.visit_itrace_start(p.parse()?, metadata),
582            PERF_RECORD_LOST_SAMPLES => visitor.visit_lost_samples(p.parse()?, metadata),
583            PERF_RECORD_SWITCH_CPU_WIDE => visitor.visit_switch_cpu_wide(p.parse()?, metadata),
584            PERF_RECORD_NAMESPACES => visitor.visit_namespaces(p.parse()?, metadata),
585            PERF_RECORD_KSYMBOL => visitor.visit_ksymbol(p.parse()?, metadata),
586            PERF_RECORD_BPF_EVENT => visitor.visit_bpf_event(p.parse()?, metadata),
587            PERF_RECORD_CGROUP => visitor.visit_cgroup(p.parse()?, metadata),
588            PERF_RECORD_TEXT_POKE => visitor.visit_text_poke(p.parse()?, metadata),
589            PERF_RECORD_AUX_OUTPUT_HW_ID => visitor.visit_aux_output_hw_id(p.parse()?, metadata),
590            _ => visitor.visit_unknown(p.parse_rest()?, metadata),
591        })
592    }
593
594    /// Same as [`parse_record`](Self::parse_record) but required that the
595    /// header be provided.
596    pub fn parse_record_with_header<V: Visitor<'p>>(
597        &mut self,
598        visitor: V,
599        header: bindings::perf_event_header,
600    ) -> ParseResult<V::Output> {
601        let (p, metadata) = self.parse_metadata_with_header_impl(header)?;
602
603        match p.data.as_slice() {
604            Some(data) => {
605                // Fast path: the data is all in one contiguous borrowed slice so we can
606                //            parse based on that.
607                let p = Parser::new(data, p.config);
608                p.parse_record_impl(visitor, metadata)
609            }
610            // Slow path: we have either an unowned slice or multiple slices so the ParseBuf
611            //            implementation needs to do more work to handle that.
612            None => p.parse_record_impl(visitor, metadata),
613        }
614    }
615}
616
617impl<'p> Parse<'p> for u8 {
618    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
619    where
620        E: Endian,
621        B: ParseBuf<'p>,
622    {
623        p.parse_u8()
624    }
625}
626
627impl<'p> Parse<'p> for u16 {
628    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
629    where
630        E: Endian,
631        B: ParseBuf<'p>,
632    {
633        p.parse_u16()
634    }
635}
636
637impl<'p> Parse<'p> for u32 {
638    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
639    where
640        E: Endian,
641        B: ParseBuf<'p>,
642    {
643        p.parse_u32()
644    }
645}
646
647impl<'p> Parse<'p> for u64 {
648    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
649    where
650        E: Endian,
651        B: ParseBuf<'p>,
652    {
653        p.parse_u64()
654    }
655}
656
657impl<'p, const N: usize> Parse<'p> for [u8; N] {
658    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
659    where
660        E: Endian,
661        B: ParseBuf<'p>,
662    {
663        p.parse_array()
664    }
665}
666
667impl<'p> Parse<'p> for bindings::perf_event_header {
668    fn parse<B, E>(p: &mut Parser<B, E>) -> ParseResult<Self>
669    where
670        E: Endian,
671        B: ParseBuf<'p>,
672    {
673        Ok(Self {
674            type_: p.parse()?,
675            misc: p.parse()?,
676            size: p.parse()?,
677        })
678    }
679}
680
681#[cfg(test)]
682mod tests {
683    use super::*;
684    use crate::endian::Native;
685
686    #[test]
687    fn parse_rest() {
688        let data: &[u8] = &[1, 2, 3, 4, 5];
689        let mut parser = Parser::new(data, ParseConfig::<Native>::default());
690        let rest = parser.parse_rest().unwrap();
691
692        assert_eq!(data, &*rest);
693    }
694}