11use std:: fmt:: { self , Display , Formatter } ;
2- use std:: fs:: File ;
2+ use std:: fs:: File as FsFile ; // Rename to avoid conflict with file::File
33use std:: io:: { Cursor , Read } ;
44use std:: path:: Path ;
55
66use binrw:: { binrw, BinRead } ;
7+ use file:: File ;
78
89use crate :: error:: FilesLumError ;
910use 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}
3055impl 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}
110133impl 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}
0 commit comments