nrbf_parser/
records.rs

1// nrbf-parser - A high-performance MS-NRBF binary parser and encoder.
2// Copyright (C) 2026  driedpampas@proton.me
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17use crate::error::Result;
18use serde::{Deserialize, Serialize};
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
21pub enum RecordType {
22    SerializedStreamHeader = 0,
23    ClassWithId = 1,
24    SystemClassWithMembers = 2,
25    ClassWithMembers = 3,
26    SystemClassWithMembersAndTypes = 4,
27    ClassWithMembersAndTypes = 5,
28    BinaryObjectString = 6,
29    BinaryArray = 7,
30    MemberPrimitiveTyped = 8,
31    MemberReference = 9,
32    ObjectNull = 10,
33    MessageEnd = 11,
34    BinaryLibrary = 12,
35    ObjectNullMultiple256 = 13,
36    ObjectNullMultiple = 14,
37    ArraySinglePrimitive = 15,
38    ArraySingleObject = 16,
39    ArraySingleString = 17,
40    BinaryMethodCall = 21,
41    BinaryMethodReturn = 22,
42}
43
44impl TryFrom<u8> for RecordType {
45    type Error = crate::error::Error;
46
47    fn try_from(value: u8) -> Result<Self> {
48        match value {
49            0 => Ok(RecordType::SerializedStreamHeader),
50            1 => Ok(RecordType::ClassWithId),
51            2 => Ok(RecordType::SystemClassWithMembers),
52            3 => Ok(RecordType::ClassWithMembers),
53            4 => Ok(RecordType::SystemClassWithMembersAndTypes),
54            5 => Ok(RecordType::ClassWithMembersAndTypes),
55            6 => Ok(RecordType::BinaryObjectString),
56            7 => Ok(RecordType::BinaryArray),
57            8 => Ok(RecordType::MemberPrimitiveTyped),
58            9 => Ok(RecordType::MemberReference),
59            10 => Ok(RecordType::ObjectNull),
60            11 => Ok(RecordType::MessageEnd),
61            12 => Ok(RecordType::BinaryLibrary),
62            13 => Ok(RecordType::ObjectNullMultiple256),
63            14 => Ok(RecordType::ObjectNullMultiple),
64            15 => Ok(RecordType::ArraySinglePrimitive),
65            16 => Ok(RecordType::ArraySingleObject),
66            17 => Ok(RecordType::ArraySingleString),
67            21 => Ok(RecordType::BinaryMethodCall),
68            22 => Ok(RecordType::BinaryMethodReturn),
69            _ => Err(crate::error::Error::InvalidRecordType(value)),
70        }
71    }
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
75pub enum BinaryType {
76    Primitive = 0,
77    String = 1,
78    Object = 2,
79    SystemClass = 3,
80    Class = 4,
81    ObjectArray = 5,
82    StringArray = 6,
83    PrimitiveArray = 7,
84}
85
86impl TryFrom<u8> for BinaryType {
87    type Error = crate::error::Error;
88
89    fn try_from(value: u8) -> Result<Self> {
90        match value {
91            0 => Ok(BinaryType::Primitive),
92            1 => Ok(BinaryType::String),
93            2 => Ok(BinaryType::Object),
94            3 => Ok(BinaryType::SystemClass),
95            4 => Ok(BinaryType::Class),
96            5 => Ok(BinaryType::ObjectArray),
97            6 => Ok(BinaryType::StringArray),
98            7 => Ok(BinaryType::PrimitiveArray),
99            _ => Err(crate::error::Error::InvalidBinaryType(value)),
100        }
101    }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
105pub enum PrimitiveType {
106    Boolean = 1,
107    Byte = 2,
108    Char = 3,
109    Decimal = 5,
110    Double = 6,
111    Int16 = 7,
112    Int32 = 8,
113    Int64 = 9,
114    SByte = 10,
115    Single = 11,
116    TimeSpan = 12,
117    DateTime = 13,
118    UInt16 = 14,
119    UInt32 = 15,
120    UInt64 = 16,
121    Null = 17,
122    String = 18,
123}
124
125impl TryFrom<u8> for PrimitiveType {
126    type Error = crate::error::Error;
127
128    fn try_from(value: u8) -> Result<Self> {
129        match value {
130            1 => Ok(PrimitiveType::Boolean),
131            2 => Ok(PrimitiveType::Byte),
132            3 => Ok(PrimitiveType::Char),
133            5 => Ok(PrimitiveType::Decimal),
134            6 => Ok(PrimitiveType::Double),
135            7 => Ok(PrimitiveType::Int16),
136            8 => Ok(PrimitiveType::Int32),
137            9 => Ok(PrimitiveType::Int64),
138            10 => Ok(PrimitiveType::SByte),
139            11 => Ok(PrimitiveType::Single),
140            12 => Ok(PrimitiveType::TimeSpan),
141            13 => Ok(PrimitiveType::DateTime),
142            14 => Ok(PrimitiveType::UInt16),
143            15 => Ok(PrimitiveType::UInt32),
144            16 => Ok(PrimitiveType::UInt64),
145            17 => Ok(PrimitiveType::Null),
146            18 => Ok(PrimitiveType::String),
147            _ => Err(crate::error::Error::InvalidPrimitiveType(value)),
148        }
149    }
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct SerializationHeader {
154    pub root_id: i32,
155    pub header_id: i32,
156    pub major_version: i32,
157    pub minor_version: i32,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct BinaryLibrary {
162    pub library_id: i32,
163    pub library_name: String,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct ClassInfo {
168    pub object_id: i32,
169    pub name: String,
170    pub member_count: i32,
171    pub member_names: Vec<String>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct ClassWithMembersAndTypes {
176    pub class_info: ClassInfo,
177    pub member_type_info: MemberTypeInfo,
178    pub library_id: i32,
179    pub member_values: Vec<ObjectValue>,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct SystemClassWithMembersAndTypes {
184    pub class_info: ClassInfo,
185    pub member_type_info: MemberTypeInfo,
186    pub member_values: Vec<ObjectValue>,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct MemberTypeInfo {
191    pub binary_type_enums: Vec<BinaryType>,
192    pub additional_infos: Vec<AdditionalTypeInfo>,
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub enum AdditionalTypeInfo {
197    Primitive(PrimitiveType),
198    SystemClass(String),
199    Class(ClassTypeInfo),
200    None,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
204pub struct ClassTypeInfo {
205    pub type_name: String,
206    pub library_id: i32,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
210pub enum ObjectValue {
211    Primitive(PrimitiveValue),
212    Record(Box<Record>),
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
216pub enum PrimitiveValue {
217    Boolean(bool),
218    Byte(u8),
219    Char(char),
220    Decimal(String),
221    Double(f64),
222    Int16(i16),
223    Int32(i32),
224    Int64(i64),
225    SByte(i8),
226    Single(f32),
227    TimeSpan(i64),
228    DateTime(u64),
229    UInt16(u16),
230    UInt32(u32),
231    UInt64(u64),
232    String(String),
233    Null,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct ValueWithCode {
238    pub primitive_type_enum: PrimitiveType,
239    pub value: PrimitiveValue,
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
243pub struct SystemClassWithMembers {
244    pub class_info: ClassInfo,
245    pub member_values: Vec<ObjectValue>,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct ClassWithMembers {
250    pub class_info: ClassInfo,
251    pub library_id: i32,
252    pub member_values: Vec<ObjectValue>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct ObjectNullMultiple {
257    pub null_count: i32,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct ObjectNullMultiple256 {
262    pub null_count: u8,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct BinaryArray {
267    pub object_id: i32,
268    pub binary_array_type_enum: u8, // BinaryArrayTypeEnumeration
269    pub rank: i32,
270    pub lengths: Vec<i32>,
271    pub lower_bounds: Option<Vec<i32>>,
272    pub type_enum: BinaryType,
273    pub additional_type_info: AdditionalTypeInfo,
274    pub element_values: Vec<ObjectValue>,
275}
276
277#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct ArraySingleObject {
279    pub object_id: i32,
280    pub length: i32,
281    pub element_values: Vec<ObjectValue>,
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
285pub struct ArraySinglePrimitive {
286    pub object_id: i32,
287    pub length: i32,
288    pub primitive_type_enum: PrimitiveType,
289    pub element_values: Vec<PrimitiveValue>,
290}
291
292#[derive(Debug, Clone, Serialize, Deserialize)]
293pub struct ArraySingleString {
294    pub object_id: i32,
295    pub length: i32,
296    pub element_values: Vec<ObjectValue>,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct ClassWithId {
301    pub object_id: i32,
302    pub metadata_id: i32,
303    pub member_values: Vec<ObjectValue>,
304}
305
306#[derive(Debug, Clone, Serialize, Deserialize)]
307pub enum Record {
308    SerializationHeader(SerializationHeader),
309    BinaryLibrary(BinaryLibrary),
310    ClassWithMembersAndTypes(ClassWithMembersAndTypes),
311    SystemClassWithMembersAndTypes(SystemClassWithMembersAndTypes),
312    SystemClassWithMembers(SystemClassWithMembers),
313    ClassWithMembers(ClassWithMembers),
314    ClassWithId(ClassWithId),
315    BinaryObjectString {
316        object_id: i32,
317        value: String,
318    },
319    BinaryArray(BinaryArray),
320    ArraySingleObject(ArraySingleObject),
321    ArraySinglePrimitive(ArraySinglePrimitive),
322    ArraySingleString(ArraySingleString),
323    MemberPrimitiveTyped {
324        primitive_type_enum: PrimitiveType,
325        value: PrimitiveValue,
326    },
327    MemberReference {
328        id_ref: i32,
329    },
330    ObjectNull,
331    ObjectNullMultiple(ObjectNullMultiple),
332    ObjectNullMultiple256(ObjectNullMultiple256),
333    MessageEnd,
334}