1#[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
7pub struct TpmErrorValue {
8 pub offset: usize,
10
11 pub value: u64,
13
14 pub needed: usize,
16
17 pub available: usize,
19
20 pub limit: usize,
22
23 pub actual: usize,
25}
26
27impl TpmErrorValue {
28 #[must_use]
30 pub const fn new(offset: usize) -> Self {
31 Self {
32 offset,
33 value: 0,
34 needed: 0,
35 available: 0,
36 limit: 0,
37 actual: 0,
38 }
39 }
40
41 #[must_use]
43 pub const fn value(mut self, value: u64) -> Self {
44 self.value = value;
45 self
46 }
47
48 #[allow(clippy::cast_possible_truncation)]
50 #[must_use]
51 pub const fn value_usize(mut self, value: usize) -> Self {
52 self.value = value as u64;
53 self
54 }
55
56 #[must_use]
58 pub const fn actual(mut self, actual: usize) -> Self {
59 self.actual = actual;
60 self
61 }
62
63 #[must_use]
65 pub const fn size(mut self, needed: usize, available: usize) -> Self {
66 self.needed = needed;
67 self.available = available;
68 self
69 }
70
71 #[must_use]
73 pub const fn limit(mut self, limit: usize, actual: usize) -> Self {
74 self.limit = limit;
75 self.actual = actual;
76 self
77 }
78
79 #[must_use]
81 pub fn at(base: &[u8], cursor: &[u8]) -> Self {
82 Self::new(Self::offset(base, cursor))
83 }
84
85 #[must_use]
87 pub fn offset(base: &[u8], cursor: &[u8]) -> usize {
88 let base_addr = base.as_ptr() as usize;
89 let cursor_addr = cursor.as_ptr() as usize;
90
91 cursor_addr.saturating_sub(base_addr).min(base.len())
92 }
93}
94
95#[derive(Debug, PartialEq, Eq, Copy, Clone)]
100pub enum TpmError {
101 BufferOverflow(TpmErrorValue),
104
105 IntegerTooLarge(TpmErrorValue),
107
108 InvalidBoolean(TpmErrorValue),
110
111 InvalidCc(TpmErrorValue),
113
114 InvalidMagicNumber(TpmErrorValue),
117
118 InvalidRc(TpmErrorValue),
120
121 InvalidTag(TpmErrorValue),
124
125 TooManyBytes(TpmErrorValue),
127
128 TooManyItems(TpmErrorValue),
130
131 TrailingData(TpmErrorValue),
133
134 UnexpectedEnd(TpmErrorValue),
136
137 VariantNotAvailable(TpmErrorValue),
139}
140
141impl TpmError {
142 #[must_use]
144 pub const fn value(self) -> TpmErrorValue {
145 match self {
146 Self::BufferOverflow(value)
147 | Self::IntegerTooLarge(value)
148 | Self::InvalidBoolean(value)
149 | Self::InvalidCc(value)
150 | Self::InvalidMagicNumber(value)
151 | Self::InvalidRc(value)
152 | Self::InvalidTag(value)
153 | Self::TooManyBytes(value)
154 | Self::TooManyItems(value)
155 | Self::TrailingData(value)
156 | Self::UnexpectedEnd(value)
157 | Self::VariantNotAvailable(value) => value,
158 }
159 }
160}
161
162impl core::fmt::Display for TpmError {
163 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164 let (message, value) = match *self {
165 Self::BufferOverflow(value) => ("buffer overflow", value),
166 Self::InvalidBoolean(value) => ("invalid boolean value", value),
167 Self::InvalidCc(value) => ("invalid command code", value),
168 Self::InvalidMagicNumber(value) => ("invalid magic number", value),
169 Self::InvalidRc(value) => ("invalid response code", value),
170 Self::InvalidTag(value) => ("invalid tag", value),
171 Self::IntegerTooLarge(value) => ("integer overflow", value),
172 Self::TooManyBytes(value) => ("buffer capacity surpassed", value),
173 Self::TooManyItems(value) => ("list capacity surpassed", value),
174 Self::TrailingData(value) => ("trailing data", value),
175 Self::UnexpectedEnd(value) => ("unexpected end", value),
176 Self::VariantNotAvailable(value) => ("enum variant is not available", value),
177 };
178
179 write!(f, "{message} at offset {}", value.offset)?;
180 if value.value != 0 {
181 write!(f, ", value=0x{:x}", value.value)?;
182 }
183 if value.needed != 0 || value.available != 0 {
184 write!(
185 f,
186 ", needed={}, available={}",
187 value.needed, value.available
188 )?;
189 }
190 if value.limit != 0 || value.actual != 0 {
191 write!(f, ", limit={}, actual={}", value.limit, value.actual)?;
192 }
193
194 Ok(())
195 }
196}
197
198impl core::error::Error for TpmError {}
199
200pub type TpmResult<T> = Result<T, TpmError>;