Skip to content

Commit 2717db4

Browse files
committed
feat: added parser for FILES.LUM
1 parent 97222a3 commit 2717db4

File tree

3 files changed

+140
-15
lines changed

3 files changed

+140
-15
lines changed

arinc-explorer/src/files/file.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use std::fmt::{self, Display, Formatter};
2+
3+
use binrw::binrw;
4+
5+
use crate::utils::vec16_to_string;
6+
7+
#[binrw]
8+
#[brw(big)]
9+
#[derive(Debug, Clone, Eq, PartialEq, Default)]
10+
pub struct File {
11+
file_pointer: u16,
12+
file_name_length: u16, // number of chars
13+
14+
#[br(count = file_name_length.div_ceil(2))]
15+
file_name: Vec<u16>,
16+
17+
file_pathname_length: u16, // number of chars
18+
19+
#[br(count = file_pathname_length.div_ceil(2))]
20+
file_pathname: Vec<u16>,
21+
22+
member_sequence_number: u16,
23+
file_crc: u16,
24+
// Seems like the following fields don't exist
25+
// file_check_value_length: u16,
26+
// #[br(if(file_check_value_length!=0))]
27+
// file_check_value_type: Option<u16>,
28+
29+
// #[br(if(file_check_value_length!=0), count = file_check_value_length.div_ceil(2))]
30+
// file_check_value: Option<Vec<u16>>,
31+
// Expansion point no2
32+
}
33+
impl File {
34+
pub fn get_file_name(&self) -> String {
35+
// If filename_length is odd, an extra NUL byte is added at the end.
36+
// This function removes the NUL byte if it exists.
37+
vec16_to_string(&self.file_name, self.file_name_length as usize)
38+
}
39+
40+
pub fn get_file_pathname(&self) -> String {
41+
// If file_pathname_length is odd, an extra NUL byte is added at the end.
42+
// This function removes the NUL byte if it exists.
43+
vec16_to_string(&self.file_pathname, self.file_pathname_length as usize)
44+
}
45+
}
46+
impl Display for File {
47+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
48+
write!(
49+
f,
50+
" \
51+
\t{} Offsets\n \
52+
\t{} Chars in Filename\n \
53+
\t{} Filename\n \
54+
\t{} Chars in File Pathname\n \
55+
\t{} File Pathname\n \
56+
\t{} Sequence number\n \
57+
\t0x{:x} CRC\n \
58+
\n",
59+
self.file_pointer,
60+
self.file_name_length,
61+
self.get_file_name(),
62+
self.file_pathname_length,
63+
self.get_file_pathname(),
64+
self.member_sequence_number,
65+
self.file_crc
66+
)
67+
}
68+
}

arinc-explorer/src/files/mod.rs

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
use std::fmt::{self, Display, Formatter};
2-
use std::fs::File;
2+
use std::fs::File as FsFile; // Rename to avoid conflict with file::File
33
use std::io::{Cursor, Read};
44
use std::path::Path;
55

66
use binrw::{binrw, BinRead};
7+
use file::File;
78

89
use crate::error::FilesLumError;
910
use crate::file_class::FileClass;
10-
use crate::utils::combine_words;
11+
use crate::utils::{combine_words, vec16_to_string};
12+
13+
mod file;
1114

1215
#[binrw]
1316
#[brw(big)]
@@ -23,9 +26,31 @@ pub struct FilesLum {
2326
pointer_to_number_of_media_set_files_lsb: u16,
2427
pointer_to_user_defined_data_msb: u16,
2528
pointer_to_user_defined_data_lsb: u16,
26-
pointer_to_file_check_value_length_msb: u16,
27-
pointer_to_file_check_value_length_lsb: u16,
29+
// Seems like pointer_to_file_check_value_length doesn't exist
30+
// pointer_to_file_check_value_length_msb: u16,
31+
// pointer_to_file_check_value_length_lsb: u16,
2832
// Expansion point no1
33+
media_set_pn_length: u16, // number of chars
34+
35+
#[br(count = media_set_pn_length.div_ceil(2))]
36+
media_set_pn: Vec<u16>, // It is always an even length
37+
media_sequence_number_x: u8,
38+
number_of_media_set_members_y: u8,
39+
number_of_media_set_files: u16,
40+
41+
#[br(count = number_of_media_set_files)]
42+
media_set_files: Vec<File>,
43+
// Expansion point no3
44+
#[br(if(combine_words(pointer_to_user_defined_data_msb, pointer_to_user_defined_data_lsb)!=0), count = (combine_words(file_length_msb, file_length_lsb) - combine_words(pointer_to_user_defined_data_msb, pointer_to_user_defined_data_lsb) - 1).div_ceil(2))]
45+
user_defined_data: Option<Vec<u16>>,
46+
// Seems like the following fields don't exist
47+
// #[br(if(combine_words(pointer_to_file_check_value_length_msb, pointer_to_file_check_value_length_lsb)!=0))]
48+
// file_check_value_length: Option<u16>,
49+
// #[br(if(file_check_value_length!=0))]
50+
// file_check_value_type: Option<u16>,
51+
// #[br(if(file_check_value_length!=0), count = file_check_value_length.div_ceil(2))]
52+
// file_check_value: Option<Vec<u16>>,
53+
file_crc: u16,
2954
}
3055
impl FilesLum {
3156
/// Constructs a new [`FilesLum`] object.
@@ -42,7 +67,7 @@ impl FilesLum {
4267
/// Returns [`Err`] if the file is missing or if there is a problem reading
4368
/// the file into the [`FilesLum`] struct.
4469
pub fn new(path: &Path) -> Result<Self, FilesLumError> {
45-
let mut file = File::open(path)?;
70+
let mut file = FsFile::open(path)?;
4671
let mut buf = Vec::new();
4772
file.read_to_end(&mut buf)?;
4873
let files_lum = FilesLum::read(&mut Cursor::new(buf))?;
@@ -98,26 +123,44 @@ impl FilesLum {
98123
)
99124
}
100125

101-
// Returns the offset in 16-bit words from the beginning of the file
102126
#[must_use]
103-
pub fn get_pointer_to_file_check_value_length(&self) -> u32 {
104-
combine_words(
105-
self.pointer_to_file_check_value_length_msb,
106-
self.pointer_to_file_check_value_length_lsb,
107-
)
127+
pub fn get_media_set_pn(&self) -> String {
128+
// If media_set_pn_length is odd, an extra NUL byte is added at the end.
129+
// This function removes the NUL byte if it exists.
130+
vec16_to_string(&self.media_set_pn, self.media_set_pn_length as usize)
108131
}
109132
}
110133
impl Display for FilesLum {
111134
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
112135
write!(
113136
f,
114-
"{} Bytes\n{}\n{} | {} | {} | {:x} Offsets",
137+
" \
138+
{} Bytes\n \
139+
{}\n \
140+
{} | {} | {} Offsets\n \
141+
{} Chars in Media Set PN\n \
142+
{} Media Set PN\n \
143+
{} Media number\n \
144+
{} Total Media sets\n \
145+
{} Total Media set files\n \
146+
{}\n \
147+
0x{:x} CRC\n \
148+
",
115149
self.get_file_length() * 2,
116150
self.get_file_type_string(),
117151
self.get_pointer_to_media_set_pn_length(),
118152
self.get_pointer_to_number_of_media_set_files(),
119153
self.get_pointer_to_user_defined_data(),
120-
self.get_pointer_to_file_check_value_length()
154+
self.media_set_pn_length,
155+
self.get_media_set_pn(),
156+
self.media_sequence_number_x,
157+
self.number_of_media_set_members_y,
158+
self.number_of_media_set_files,
159+
self.media_set_files
160+
.iter()
161+
.map(|f| format!("{f}"))
162+
.fold(String::new(), |acc, arg| acc + arg.as_str()),
163+
self.file_crc
121164
)
122165
}
123166
}
@@ -128,13 +171,27 @@ mod tests {
128171

129172
use super::*;
130173

131-
#[ignore = "File not found"]
132174
#[test]
133175
fn test_simple_files_lum() {
134176
// 1 hex = 4 bits
135177
// 4 hex = 16 bits = 2 bytes
136-
let file = PathBuf::from("../../FILES.LUM");
178+
let file = PathBuf::from("../test-data/FILES.LUM");
137179
let files_lum = FilesLum::new(file.as_path()).unwrap();
138180
println!("{files_lum}");
181+
182+
assert_eq!(files_lum.get_file_length(), 300);
183+
assert_eq!(files_lum.media_file_format_verion, 0x8002);
184+
assert_eq!(files_lum.get_pointer_to_media_set_pn_length(), 0x9);
185+
assert_eq!(files_lum.get_pointer_to_number_of_media_set_files(), 0x10);
186+
assert_eq!(files_lum.get_pointer_to_user_defined_data(), 0x0);
187+
assert_eq!(files_lum.media_set_pn_length, 10);
188+
assert_eq!(files_lum.media_set_pn.len(), 5);
189+
assert_eq!(files_lum.get_media_set_pn(), "ABC1813001");
190+
assert_eq!(files_lum.media_sequence_number_x, 1);
191+
assert_eq!(files_lum.number_of_media_set_members_y, 1);
192+
assert_eq!(files_lum.number_of_media_set_files, 14);
193+
assert_eq!(files_lum.media_set_files.len(), 14);
194+
assert_eq!(files_lum.user_defined_data, None);
195+
assert_eq!(files_lum.file_crc, 0x3BE8);
139196
}
140197
}

test-data/FILES.LUM

600 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)