Decoder

Struct Decoder 

Source
pub struct Decoder<R: Read> {
    pub library_registry: HashMap<i32, String>,
    pub offset: usize,
    /* private fields */
}
Expand description

A decoder for MS-NRBF binary streams.

Fields§

§library_registry: HashMap<i32, String>

Registry of libraries by ID.

§offset: usize

Current offset in the stream.

Implementations§

Source§

impl<R: Read> Decoder<R>

Source

pub fn new(reader: R) -> Self

Creates a new decoder from a reader.

Examples found in repository?
examples/parse_meta.rs (line 32)
23fn main() -> Result<(), Box<dyn std::error::Error>> {
24    let args: Vec<String> = env::args().collect();
25    if args.len() < 2 {
26        eprintln!("Usage: {} <nrbf_file> [output_json]", args[0]);
27        std::process::exit(1);
28    }
29
30    let file = File::open(&args[1])?;
31    let reader = BufReader::new(file);
32    let mut decoder = Decoder::new(reader);
33
34    let mut records = Vec::new();
35    while let Some(record) = decoder.decode_next()? {
36        records.push(record);
37        if let Record::MessageEnd = records.last().unwrap() {
38            break;
39        }
40    }
41
42    let output_path = args.get(2).map(|s| s.as_str()).unwrap_or("output.json");
43    let json = serde_json::to_string_pretty(&records)?;
44
45    let mut out_file = File::create(output_path)?;
46    out_file.write_all(json.as_bytes())?;
47
48    println!(
49        "Successfully parsed {} records and saved to {}",
50        records.len(),
51        output_path
52    );
53
54    Ok(())
55}
More examples
Hide additional examples
examples/round_trip.rs (line 39)
25fn main() -> Result<(), Box<dyn std::error::Error>> {
26    let args: Vec<String> = env::args().collect();
27    if args.len() < 2 {
28        eprintln!("Usage: {} <nrbf_file>", args[0]);
29        std::process::exit(1);
30    }
31
32    let input_path = &args[1];
33    println!("Reading original file: {}", input_path);
34    let file = File::open(input_path)?;
35    let mut original_data = Vec::new();
36    File::open(input_path)?.read_to_end(&mut original_data)?;
37
38    let reader = BufReader::new(file);
39    let mut decoder = Decoder::new(reader);
40
41    let mut records = Vec::new();
42    while let Some(record) = decoder.decode_next()? {
43        let is_end = matches!(record, Record::MessageEnd);
44        records.push(record);
45        if is_end {
46            break;
47        }
48    }
49    println!("Parsed {} records.", records.len());
50
51    // Serialize to JSON
52    let json = serde_json::to_string_pretty(&records)?;
53    let json_path = "output.json";
54    std::fs::write(json_path, &json)?;
55    println!("Saved records to {}", json_path);
56
57    // Serialize to Interleaved JSON
58    let interleaved_json = to_interleaved(&records);
59    let interleaved_json_str = serde_json::to_string_pretty(&interleaved_json)?;
60    let interleaved_path = "interleaved.json";
61    std::fs::write(interleaved_path, &interleaved_json_str)?;
62    println!("Saved interleaved records to {}", interleaved_path);
63
64    // Deserialize from JSON
65    let deserialized_records: Vec<Record> = serde_json::from_str(&json)?;
66    println!(
67        "Deserialized {} records from JSON.",
68        deserialized_records.len()
69    );
70
71    // Encode back to binary
72    let output_path = "reconstructed.meta";
73    let out_file = File::create(output_path)?;
74    let mut encoder = Encoder::new(BufWriter::new(out_file));
75
76    for record in &deserialized_records {
77        encoder.encode(record)?;
78    }
79    // Ensure everything is flushed
80    drop(encoder);
81    println!("Reconstructed binary saved to {}", output_path);
82
83    // Interleaved reconstruction check
84    println!("--- Interleaved Round Trip Check ---");
85    let interleaved_reconstructed_records = from_interleaved(interleaved_json);
86    println!(
87        "Deserialized {} records from Interleaved JSON.",
88        interleaved_reconstructed_records.len()
89    );
90
91    let interleaved_output_path = "reconstructed_interleaved.meta";
92    let int_out_file = File::create(interleaved_output_path)?;
93    let mut int_encoder = Encoder::new(BufWriter::new(int_out_file));
94
95    for record in &interleaved_reconstructed_records {
96        int_encoder.encode(record)?;
97    }
98    drop(int_encoder);
99
100    let mut int_reconstructed_data = Vec::new();
101    File::open(interleaved_output_path)?.read_to_end(&mut int_reconstructed_data)?;
102
103    if original_data == int_reconstructed_data {
104        println!("SUCCESS: Interleaved reconstructed binary is identical to original!");
105    } else {
106        println!("FAILURE: Interleaved reconstructed binary differs from original.");
107        println!(
108            "Original size: {}, Reconstructed size: {}",
109            original_data.len(),
110            int_reconstructed_data.len()
111        );
112        // Find first difference
113        let min_len = std::cmp::min(original_data.len(), int_reconstructed_data.len());
114        for i in 0..min_len {
115            if original_data[i] != int_reconstructed_data[i] {
116                println!(
117                    "First difference at offset 0x{:x}: original 0x{:02x}, reconstructed 0x{:02x}",
118                    i, original_data[i], int_reconstructed_data[i]
119                );
120                break;
121            }
122        }
123    }
124
125    Ok(())
126}
Source

pub fn decode_next(&mut self) -> Result<Option<Record>>

Decodes the next record from the stream.

Returns Ok(Some(record)) if a record was successfully read, Ok(None) if the end of the stream was reached, or an Err if parsing failed.

Examples found in repository?
examples/parse_meta.rs (line 35)
23fn main() -> Result<(), Box<dyn std::error::Error>> {
24    let args: Vec<String> = env::args().collect();
25    if args.len() < 2 {
26        eprintln!("Usage: {} <nrbf_file> [output_json]", args[0]);
27        std::process::exit(1);
28    }
29
30    let file = File::open(&args[1])?;
31    let reader = BufReader::new(file);
32    let mut decoder = Decoder::new(reader);
33
34    let mut records = Vec::new();
35    while let Some(record) = decoder.decode_next()? {
36        records.push(record);
37        if let Record::MessageEnd = records.last().unwrap() {
38            break;
39        }
40    }
41
42    let output_path = args.get(2).map(|s| s.as_str()).unwrap_or("output.json");
43    let json = serde_json::to_string_pretty(&records)?;
44
45    let mut out_file = File::create(output_path)?;
46    out_file.write_all(json.as_bytes())?;
47
48    println!(
49        "Successfully parsed {} records and saved to {}",
50        records.len(),
51        output_path
52    );
53
54    Ok(())
55}
More examples
Hide additional examples
examples/round_trip.rs (line 42)
25fn main() -> Result<(), Box<dyn std::error::Error>> {
26    let args: Vec<String> = env::args().collect();
27    if args.len() < 2 {
28        eprintln!("Usage: {} <nrbf_file>", args[0]);
29        std::process::exit(1);
30    }
31
32    let input_path = &args[1];
33    println!("Reading original file: {}", input_path);
34    let file = File::open(input_path)?;
35    let mut original_data = Vec::new();
36    File::open(input_path)?.read_to_end(&mut original_data)?;
37
38    let reader = BufReader::new(file);
39    let mut decoder = Decoder::new(reader);
40
41    let mut records = Vec::new();
42    while let Some(record) = decoder.decode_next()? {
43        let is_end = matches!(record, Record::MessageEnd);
44        records.push(record);
45        if is_end {
46            break;
47        }
48    }
49    println!("Parsed {} records.", records.len());
50
51    // Serialize to JSON
52    let json = serde_json::to_string_pretty(&records)?;
53    let json_path = "output.json";
54    std::fs::write(json_path, &json)?;
55    println!("Saved records to {}", json_path);
56
57    // Serialize to Interleaved JSON
58    let interleaved_json = to_interleaved(&records);
59    let interleaved_json_str = serde_json::to_string_pretty(&interleaved_json)?;
60    let interleaved_path = "interleaved.json";
61    std::fs::write(interleaved_path, &interleaved_json_str)?;
62    println!("Saved interleaved records to {}", interleaved_path);
63
64    // Deserialize from JSON
65    let deserialized_records: Vec<Record> = serde_json::from_str(&json)?;
66    println!(
67        "Deserialized {} records from JSON.",
68        deserialized_records.len()
69    );
70
71    // Encode back to binary
72    let output_path = "reconstructed.meta";
73    let out_file = File::create(output_path)?;
74    let mut encoder = Encoder::new(BufWriter::new(out_file));
75
76    for record in &deserialized_records {
77        encoder.encode(record)?;
78    }
79    // Ensure everything is flushed
80    drop(encoder);
81    println!("Reconstructed binary saved to {}", output_path);
82
83    // Interleaved reconstruction check
84    println!("--- Interleaved Round Trip Check ---");
85    let interleaved_reconstructed_records = from_interleaved(interleaved_json);
86    println!(
87        "Deserialized {} records from Interleaved JSON.",
88        interleaved_reconstructed_records.len()
89    );
90
91    let interleaved_output_path = "reconstructed_interleaved.meta";
92    let int_out_file = File::create(interleaved_output_path)?;
93    let mut int_encoder = Encoder::new(BufWriter::new(int_out_file));
94
95    for record in &interleaved_reconstructed_records {
96        int_encoder.encode(record)?;
97    }
98    drop(int_encoder);
99
100    let mut int_reconstructed_data = Vec::new();
101    File::open(interleaved_output_path)?.read_to_end(&mut int_reconstructed_data)?;
102
103    if original_data == int_reconstructed_data {
104        println!("SUCCESS: Interleaved reconstructed binary is identical to original!");
105    } else {
106        println!("FAILURE: Interleaved reconstructed binary differs from original.");
107        println!(
108            "Original size: {}, Reconstructed size: {}",
109            original_data.len(),
110            int_reconstructed_data.len()
111        );
112        // Find first difference
113        let min_len = std::cmp::min(original_data.len(), int_reconstructed_data.len());
114        for i in 0..min_len {
115            if original_data[i] != int_reconstructed_data[i] {
116                println!(
117                    "First difference at offset 0x{:x}: original 0x{:02x}, reconstructed 0x{:02x}",
118                    i, original_data[i], int_reconstructed_data[i]
119                );
120                break;
121            }
122        }
123    }
124
125    Ok(())
126}

Auto Trait Implementations§

§

impl<R> Freeze for Decoder<R>
where R: Freeze,

§

impl<R> RefUnwindSafe for Decoder<R>
where R: RefUnwindSafe,

§

impl<R> Send for Decoder<R>
where R: Send,

§

impl<R> Sync for Decoder<R>
where R: Sync,

§

impl<R> Unpin for Decoder<R>
where R: Unpin,

§

impl<R> UnwindSafe for Decoder<R>
where R: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.