1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(feature = "paranoid", forbid(unsafe_code))]
3
4extern crate alloc;
5
6use alloc::string::String;
7use alloc::vec::Vec;
8use core::fmt;
9
10pub type Result<T> = core::result::Result<T, Error>;
11
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct Error {
14 kind: ErrorKind,
15 offset: Option<usize>,
16 detail: Option<String>,
17}
18
19impl Error {
20 pub const fn new(kind: ErrorKind) -> Self {
21 Self {
22 kind,
23 offset: None,
24 detail: None,
25 }
26 }
27
28 pub const fn at(kind: ErrorKind, offset: usize) -> Self {
29 Self {
30 kind,
31 offset: Some(offset),
32 detail: None,
33 }
34 }
35
36 #[must_use]
37 pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
38 self.detail = Some(detail.into());
39 self
40 }
41
42 pub const fn kind(&self) -> ErrorKind {
43 self.kind
44 }
45
46 pub const fn offset(&self) -> Option<usize> {
47 self.offset
48 }
49
50 pub fn detail(&self) -> Option<&str> {
51 self.detail.as_deref()
52 }
53}
54
55impl fmt::Display for Error {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 write!(f, "{:?}", self.kind)?;
58 if let Some(offset) = self.offset {
59 write!(f, " at byte {offset}")?;
60 }
61 if let Some(detail) = &self.detail {
62 write!(f, ": {detail}")?;
63 }
64 Ok(())
65 }
66}
67
68#[cfg(feature = "std")]
69impl std::error::Error for Error {}
70
71#[derive(Clone, Copy, Debug, Eq, PartialEq)]
72pub enum ErrorKind {
73 Truncated,
74 Malformed,
75 Unsupported,
76 LimitExceeded,
77 ChecksumMismatch,
78 InvalidGraph,
79 InvalidType,
80 IntegerOverflow,
81}
82
83#[derive(Clone, Copy, Debug, Eq, PartialEq)]
84pub struct Limits {
85 pub max_frame_bytes: usize,
86 pub max_decoded_bytes: usize,
87 pub max_chunks: usize,
88 pub max_nodes: usize,
89 pub max_streams: usize,
90 pub max_transform_header_bytes: usize,
91 pub max_stored_stream_bytes: usize,
92 pub max_buffer_bytes: usize,
93 pub max_graph_depth: usize,
94 pub max_expansion_ratio: usize,
95}
96
97impl Limits {
98 pub const fn strict() -> Self {
99 Self {
100 max_frame_bytes: 64 * 1024 * 1024,
101 max_decoded_bytes: 64 * 1024 * 1024,
102 max_chunks: 16_384,
103 max_nodes: 65_536,
104 max_streams: 131_072,
105 max_transform_header_bytes: 16 * 1024 * 1024,
106 max_stored_stream_bytes: 64 * 1024 * 1024,
107 max_buffer_bytes: 64 * 1024 * 1024,
108 max_graph_depth: 1024,
109 max_expansion_ratio: 256,
110 }
111 }
112
113 pub const fn paranoid() -> Self {
114 Self {
115 max_frame_bytes: 16 * 1024 * 1024,
116 max_decoded_bytes: 16 * 1024 * 1024,
117 max_chunks: 4096,
118 max_nodes: 16_384,
119 max_streams: 32_768,
120 max_transform_header_bytes: 4 * 1024 * 1024,
121 max_stored_stream_bytes: 16 * 1024 * 1024,
122 max_buffer_bytes: 16 * 1024 * 1024,
123 max_graph_depth: 256,
124 max_expansion_ratio: 64,
125 }
126 }
127}
128
129impl Default for Limits {
130 fn default() -> Self {
131 if cfg!(feature = "paranoid") {
132 Self::paranoid()
133 } else {
134 Self::strict()
135 }
136 }
137}
138
139#[derive(Clone, Debug, Eq, PartialEq)]
140pub struct FrameInfo {
141 pub format_version: u32,
142 pub frame_bytes: usize,
143 pub header_bytes: usize,
144 pub decoded_bytes: Option<usize>,
145 pub chunks: usize,
146 pub inputs: usize,
147 pub output_types: Vec<FrameValueType>,
148 pub output_sizes: Vec<Option<u64>>,
149 pub output_elements: Vec<Option<u64>>,
150 pub transforms: usize,
151 pub stored_streams: usize,
152 pub regenerated_streams: usize,
153 pub has_decoded_checksum: bool,
154 pub has_encoded_checksum: bool,
155 pub has_comment: bool,
156 pub comment: Option<Vec<u8>>,
157 pub dictionary_bundle_id: Option<Vec<u8>>,
158}
159
160#[derive(Clone, Copy, Debug, Eq, PartialEq)]
161pub enum FrameValueType {
162 Serial,
163 Struct,
164 Numeric,
165 String,
166}