1use binrw::{meta::ReadEndian, prelude::*};
4
5pub trait FileInfoType:
11 Sized + for<'a> BinRead<Args<'static> = (Self::Class,)> + ReadEndian + std::fmt::Debug
12{
13 type Class;
15
16 fn class(&self) -> Self::Class;
18}
19
20macro_rules! file_info_classes {
24 (
25 $(#[doc = $docstring:literal])*
26 $svis:vis $name:ident {
27 $($vis:vis $field_name:ident = $cid:literal,)+
28 }, $brw_ty:ty
29 ) => {
30 #[allow(unused_imports)]
31 use binrw::prelude::*;
32 pastey::paste! {
33 #[doc = concat!("[`", stringify!($name), "`][crate::", stringify!($name), "].")]
35 pub trait [<$name Value>] :
41 TryFrom<$name, Error = $crate::SmbFsccError>
42 + Send + 'static
43 + Into<$name>
44 + for <'a> [<Bin $brw_ty>]<Args<'a> = ()> {
45 const CLASS_ID: [<$name Class>];
46 }
47
48 #[doc = concat!("[`", stringify!($name), "`][crate::", stringify!($name), "]")]
50 #[binrw::binrw]
53 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
54 #[brw(repr(u8))]
55 $svis enum [<$name Class>] {
56 $(
57 $vis [<$field_name Information>] = $cid,
58 )*
59 }
60
61 $(#[doc = $docstring])*
62 #[doc = concat!("- [`", stringify!([<$name Class>]), "`][crate::", stringify!([<$name Class>]), "] - class IDs")]
65 #[doc = concat!("- [`", stringify!([<$name Value>]), "`][crate::", stringify!([<$name Value>]), "] - value trait")]
66 #[binrw::binrw]
69 #[derive(Debug, PartialEq, Eq)]
70 #[brw(little)]
71 #[br(import(c: [<$name Class>]))]
72 $svis enum $name {
73 $(
74 #[br(pre_assert(matches!(c, [<$name Class>]::[<$field_name Information>])))]
75 [<$field_name Information>]([<File $field_name Information>]),
76 )*
77 }
78
79 impl std::fmt::Display for [<$name Class>] {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 match self {
82 $(
83 [<$name Class>]::[<$field_name Information>] => write!(f, stringify!([<$field_name Information>])),
84 )*
85 }
86 }
87 }
88
89 impl $crate::FileInfoType for $name {
90 type Class = [<$name Class>];
91 fn class(&self) -> Self::Class {
92 match self {
93 $(
94 $name::[<$field_name Information>](_) => [<$name Class>]::[<$field_name Information>],
95 )*
96 }
97 }
98 }
99
100 $(
101 impl From<[<File $field_name Information>]> for $name {
102 fn from(value: [<File $field_name Information>]) -> $name {
103 $name::[<$field_name Information>](value)
104 }
105 }
106
107 impl TryFrom<$name> for [<File $field_name Information>] {
108 type Error = $crate::SmbFsccError;
109
110 fn try_from(value: $name) -> Result<Self, Self::Error> {
111 pub use $crate::FileInfoType;
112 match value {
113 $name::[<$field_name Information>](v) => Ok(v),
114 _ => Err($crate::SmbFsccError::UnexpectedInformationType(stringify!([<$field_name Information>]), <Self as [<$name Value>]>::CLASS_ID as u8, value.class() as u8)),
115 }
116 }
117 }
118
119 impl [<$name Value>] for [<File $field_name Information>] {
120 const CLASS_ID: [<$name Class>] = [<$name Class>]::[<$field_name Information>];
121 }
122 )*
123 }
124 }
125}
126
127pub(crate) use file_info_classes;