1use binrw::prelude::*;
4
5use smb_dtyp::binrw_util::prelude::*;
6
7#[binrw::binrw]
8#[derive(Debug, PartialEq, Eq)]
9pub struct ErrorResponse {
10 #[bw(calc = 9)]
11 #[br(assert(_structure_size == 9))]
12 _structure_size: u16,
13
14 #[bw(try_calc = error_data.len().try_into())]
15 _error_context_count: u8,
16
17 #[bw(calc = 0)]
18 _reserved: u8,
19
20 #[bw(calc = PosMarker::default())]
21 _byte_count: PosMarker<u32>,
22
23 #[br(count = _error_context_count)]
24 pub error_data: Vec<ErrorResponseContext>,
25}
26
27#[binrw::binrw]
28#[derive(Debug, PartialEq, Eq)]
29pub struct ErrorResponseContext {
30 #[brw(align_before = 8)]
34 #[bw(try_calc = error_data.len().try_into())]
35 _error_data_length: u32,
36 pub error_id: ErrorId,
37 #[br(count = _error_data_length)]
38 pub error_data: Vec<u8>,
39}
40
41impl ErrorResponse {
42 pub fn find_context(&self, id: ErrorId) -> Option<&ErrorResponseContext> {
45 self.error_data.iter().find(|c| c.error_id == id)
46 }
47}
48
49impl ErrorResponseContext {
50 pub fn as_u32(&self) -> crate::Result<u32> {
53 if self.error_data.len() == std::mem::size_of::<u32>() {
54 Ok(u32::from_le_bytes(
55 self.error_data.as_slice().try_into().unwrap(),
56 ))
57 } else {
58 Err(crate::SmbMsgError::InvalidData(
59 "Invalid error data length for u32".into(),
60 ))
61 }
62 }
63
64 pub fn as_u64(&self) -> crate::Result<u64> {
67 if self.error_data.len() == std::mem::size_of::<u64>() {
68 Ok(u64::from_le_bytes(
69 self.error_data.as_slice().try_into().unwrap(),
70 ))
71 } else {
72 Err(crate::SmbMsgError::InvalidData(
73 "Invalid error data length for u64".into(),
74 ))
75 }
76 }
77}
78
79#[binrw::binrw]
80#[derive(Debug, PartialEq, Eq)]
81#[brw(repr(u32))]
82pub enum ErrorId {
83 Default = 0,
84 ShareRedirect = 0x72645253,
85}
86
87#[cfg(test)]
88mod tests {
89 use crate::*;
90
91 test_response! {
92 error_simple, Command::Cancel => Error { error_data: vec![], } => "0900000000000000"
93 }
94}