fxt/
error.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::thread::{ProcessRef, ThreadRef};
6use flyweights::FlyStr;
7use nom::error::ErrorKind;
8use std::num::NonZeroU16;
9
10pub(crate) type ParseResult<'a, T> = nom::IResult<&'a [u8], T, ParseError>;
11
12#[derive(Debug, thiserror::Error)]
13pub enum ParseError {
14    /// We encountered a generic `nom` error while parsing.
15    #[error("nom parsing error: {1:?}")]
16    Nom(nom::error::ErrorKind, #[source] Option<Box<Self>>),
17
18    /// We encountered an error performing I/O to read the trace session.
19    #[error("failure reading the trace session")]
20    Io(#[source] std::io::Error),
21
22    /// We encountered invalid UTF-8 while parsing.
23    #[error("couldn't parse string as utf-8")]
24    InvalidUtf8(
25        #[from]
26        #[source]
27        std::str::Utf8Error,
28    ),
29
30    /// We encountered a non-magic-number record at the beginning of the session.
31    #[error("trace session didn't start with the magic number record")]
32    MissingMagicNumber,
33
34    /// We encountered an unexpected type ordinal while parsing.
35    #[error("expected type {expected} for {context}, observed type {observed}")]
36    WrongType { expected: u8, observed: u8, context: &'static str },
37
38    /// We encountered an incorrect magic number while parsing.
39    #[error("got the wrong magic number: {observed}")]
40    InvalidMagicNumber { observed: u32 },
41
42    /// We encountered an invalid reference, like a zero thread id.
43    #[error("got an invalid ref")]
44    InvalidRef,
45
46    /// We encountered an invalid length for a record.
47    #[error("invalid length prefix encountered")]
48    InvalidSize,
49}
50
51impl nom::error::ParseError<&[u8]> for ParseError {
52    fn from_error_kind(_input: &[u8], kind: nom::error::ErrorKind) -> Self {
53        ParseError::Nom(kind, None)
54    }
55
56    fn append(_input: &[u8], kind: nom::error::ErrorKind, prev: Self) -> Self {
57        ParseError::Nom(kind, Some(Box::new(prev)))
58    }
59}
60
61impl nom::error::FromExternalError<&[u8], ParseError> for ParseError {
62    fn from_external_error(_input: &[u8], _kind: ErrorKind, e: ParseError) -> Self {
63        e
64    }
65}
66
67/// Scenarios encountered during parsing that didn't prevent parsing from succeeding but which
68/// might affect analysis of the session.
69#[derive(Clone, Debug, thiserror::Error, PartialEq)]
70pub enum ParseWarning {
71    #[error("encountered unknown thread reference `{_0:?}`")]
72    UnknownThreadRef(ThreadRef),
73
74    #[error("encountered unknown process reference `{_0:?}`")]
75    UnknownProcessRef(ProcessRef),
76
77    #[error("encountered unknown trace record type {_0}")]
78    UnknownTraceRecordType(u8),
79
80    #[error("skipped arg '{name}' because of unknown type")]
81    SkippingArgWithUnknownType { name: FlyStr },
82
83    #[error("encountered unknown provider id {_0}")]
84    UnknownProviderId(u32),
85
86    #[error("encountered unknown string id {_0}")]
87    UnknownStringId(NonZeroU16),
88
89    #[error("encountered an empty string record")]
90    RecordForZeroStringId,
91
92    #[error("encountered unknown large blob type {_0}")]
93    UnknownLargeBlobType(u8),
94
95    #[error("encountered unknown metadata record type {_0}")]
96    UnknownMetadataRecordType(u8),
97
98    #[error("encountered unknown scheduling record type {_0}")]
99    UnknownSchedulingRecordType(u8),
100}