2
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
5
- use crate :: types:: { Error , FileSystemError , PtrMut , Result } ;
5
+ use crate :: types:: { ApcbContext , Error , FileSystemError , PtrMut , Result } ;
6
6
7
7
use crate :: entry:: EntryItemBody ;
8
8
use crate :: group:: { GroupItem , GroupMutItem } ;
@@ -50,29 +50,41 @@ use std::borrow::Cow;
50
50
#[ derive( Clone ) ]
51
51
pub struct ApcbIoOptions {
52
52
pub check_checksum : bool ,
53
+ pub context : ApcbContext ,
53
54
}
54
55
55
56
impl Default for ApcbIoOptions {
56
57
fn default ( ) -> Self {
57
- Self { check_checksum : true }
58
+ Self { check_checksum : true , context : ApcbContext :: default ( ) }
58
59
}
59
60
}
60
61
61
62
impl ApcbIoOptions {
62
63
pub fn builder ( ) -> Self {
63
64
Self :: default ( )
64
65
}
66
+ pub fn check_checksum ( & self ) -> bool {
67
+ self . check_checksum
68
+ }
69
+ pub fn context ( & self ) -> ApcbContext {
70
+ self . context
71
+ }
65
72
pub fn with_check_checksum ( & mut self , value : bool ) -> & mut Self {
66
73
self . check_checksum = value;
67
74
self
68
75
}
76
+ pub fn with_context ( & mut self , value : ApcbContext ) -> & mut Self {
77
+ self . context = value;
78
+ self
79
+ }
69
80
pub fn build ( & self ) -> Self {
70
81
self . clone ( )
71
82
}
72
83
}
73
84
74
85
#[ cfg_attr( feature = "std" , derive( Clone ) ) ]
75
86
pub struct Apcb < ' a > {
87
+ context : ApcbContext ,
76
88
used_size : usize ,
77
89
pub backing_store : PtrMut < ' a , [ u8 ] > ,
78
90
}
@@ -83,6 +95,11 @@ pub struct Apcb<'a> {
83
95
#[ cfg_attr( feature = "serde" , serde( deny_unknown_fields) ) ]
84
96
#[ cfg_attr( feature = "schemars" , derive( schemars:: JsonSchema ) ) ]
85
97
pub struct SerdeApcb {
98
+ /// This field is out-of-band information. At the cost of slight redundancy
99
+ /// in user config and another extra field that isn't actually in the blob,
100
+ /// we can actually handle the out-of-band information quite natually.
101
+ #[ cfg_attr( feature = "serde" , serde( default ) ) ]
102
+ pub context : ApcbContext ,
86
103
pub version : String ,
87
104
pub header : V2_HEADER ,
88
105
pub v3_header_ext : Option < V3_HEADER_EXT > ,
@@ -110,11 +127,18 @@ impl<'a> schemars::JsonSchema for Apcb<'a> {
110
127
use core:: convert:: TryFrom ;
111
128
112
129
#[ cfg( feature = "serde" ) ]
113
- impl < ' a > TryFrom < SerdeApcb > for Apcb < ' a > {
114
- type Error = Error ;
130
+ impl < ' a > Apcb < ' a > {
131
+ pub fn context ( & self ) -> ApcbContext {
132
+ self . context
133
+ }
134
+ // type Error = Error;
115
135
fn try_from ( serde_apcb : SerdeApcb ) -> Result < Self > {
116
136
let buf = Cow :: from ( vec ! [ 0xFFu8 ; Self :: MAX_SIZE ] ) ;
117
- let mut apcb = Apcb :: create ( buf, 42 , & ApcbIoOptions :: default ( ) ) ?;
137
+ let mut apcb = Apcb :: create (
138
+ buf,
139
+ 42 ,
140
+ & ApcbIoOptions :: default ( ) . with_context ( serde_apcb. context ) . build ( ) ,
141
+ ) ?;
118
142
* apcb. header_mut ( ) ? = serde_apcb. header ;
119
143
match serde_apcb. v3_header_ext {
120
144
Some ( v3) => {
@@ -204,6 +228,7 @@ impl<'a> Serialize for Apcb<'a> {
204
228
}
205
229
}
206
230
231
+ /// Note: Caller should probably verify sanity of context() afterwards
207
232
#[ cfg( feature = "serde" ) ]
208
233
impl < ' de > Deserialize < ' de > for Apcb < ' _ > {
209
234
fn deserialize < D > ( deserializer : D ) -> core:: result:: Result < Self , D :: Error >
@@ -217,11 +242,13 @@ impl<'de> Deserialize<'de> for Apcb<'_> {
217
242
}
218
243
219
244
pub struct ApcbIterMut < ' a > {
245
+ context : ApcbContext ,
220
246
buf : & ' a mut [ u8 ] ,
221
247
remaining_used_size : usize ,
222
248
}
223
249
224
250
pub struct ApcbIter < ' a > {
251
+ context : ApcbContext ,
225
252
buf : & ' a [ u8 ] ,
226
253
remaining_used_size : usize ,
227
254
}
@@ -230,7 +257,10 @@ impl<'a> ApcbIterMut<'a> {
230
257
/// It's useful to have some way of NOT mutating self.buf. This is what
231
258
/// this function does. Note: The caller needs to manually decrease
232
259
/// remaining_used_size for each call if desired.
233
- fn next_item < ' b > ( buf : & mut & ' b mut [ u8 ] ) -> Result < GroupMutItem < ' b > > {
260
+ fn next_item < ' b > (
261
+ context : ApcbContext ,
262
+ buf : & mut & ' b mut [ u8 ] ,
263
+ ) -> Result < GroupMutItem < ' b > > {
234
264
if buf. is_empty ( ) {
235
265
return Err ( Error :: FileSystem (
236
266
FileSystemError :: InconsistentHeader ,
@@ -256,7 +286,7 @@ impl<'a> ApcbIterMut<'a> {
256
286
) ) ?;
257
287
let body_len = body. len ( ) ;
258
288
259
- Ok ( GroupMutItem { header, buf : body, used_size : body_len } )
289
+ Ok ( GroupMutItem { context , header, buf : body, used_size : body_len } )
260
290
}
261
291
262
292
/// Moves the point to the group with the given GROUP_ID. Returns (offset,
@@ -273,12 +303,12 @@ impl<'a> ApcbIterMut<'a> {
273
303
if buf. is_empty ( ) {
274
304
break ;
275
305
}
276
- let group = ApcbIterMut :: next_item ( & mut buf) ?;
306
+ let group = ApcbIterMut :: next_item ( self . context , & mut buf) ?;
277
307
let group_size = group. header . group_size . get ( ) ;
278
308
if group. header . group_id . get ( ) == group_id {
279
309
return Ok ( ( offset, group_size as usize ) ) ;
280
310
}
281
- let group = ApcbIterMut :: next_item ( & mut self . buf ) ?;
311
+ let group = ApcbIterMut :: next_item ( self . context , & mut self . buf ) ?;
282
312
let group_size = group. header . group_size . get ( ) as usize ;
283
313
offset = offset
284
314
. checked_add ( group_size)
@@ -295,7 +325,7 @@ impl<'a> ApcbIterMut<'a> {
295
325
296
326
pub ( crate ) fn next1 ( & mut self ) -> Result < GroupMutItem < ' a > > {
297
327
assert ! ( self . remaining_used_size != 0 , "Internal error" ) ;
298
- let item = Self :: next_item ( & mut self . buf ) ?;
328
+ let item = Self :: next_item ( self . context , & mut self . buf ) ?;
299
329
let group_size = item. header . group_size . get ( ) as usize ;
300
330
if group_size <= self . remaining_used_size {
301
331
self . remaining_used_size -= group_size;
@@ -324,7 +354,10 @@ impl<'a> ApcbIter<'a> {
324
354
/// It's useful to have some way of NOT mutating self.buf. This is what
325
355
/// this function does. Note: The caller needs to manually decrease
326
356
/// remaining_used_size for each call if desired.
327
- fn next_item < ' b > ( buf : & mut & ' b [ u8 ] ) -> Result < GroupItem < ' b > > {
357
+ fn next_item < ' b > (
358
+ context : ApcbContext ,
359
+ buf : & mut & ' b [ u8 ] ,
360
+ ) -> Result < GroupItem < ' b > > {
328
361
if buf. is_empty ( ) {
329
362
return Err ( Error :: FileSystem (
330
363
FileSystemError :: InconsistentHeader ,
@@ -351,12 +384,12 @@ impl<'a> ApcbIter<'a> {
351
384
352
385
let body_len = body. len ( ) ;
353
386
354
- Ok ( GroupItem { header, buf : body, used_size : body_len } )
387
+ Ok ( GroupItem { context , header, buf : body, used_size : body_len } )
355
388
}
356
389
357
390
pub ( crate ) fn next1 ( & mut self ) -> Result < GroupItem < ' a > > {
358
391
assert ! ( self . remaining_used_size != 0 , "Internal error" ) ;
359
- let item = Self :: next_item ( & mut self . buf ) ?;
392
+ let item = Self :: next_item ( self . context , & mut self . buf ) ?;
360
393
let group_size = item. header . group_size . get ( ) as usize ;
361
394
if group_size <= self . remaining_used_size {
362
395
self . remaining_used_size -= group_size;
@@ -400,7 +433,7 @@ impl<'a> Apcb<'a> {
400
433
const ROME_VERSION : u16 = 0x30 ;
401
434
const V3_HEADER_EXT_SIZE : usize =
402
435
size_of :: < V2_HEADER > ( ) + size_of :: < V3_HEADER_EXT > ( ) ;
403
- pub const MAX_SIZE : usize = 0x6500 ;
436
+ pub const MAX_SIZE : usize = 0x8000 ;
404
437
405
438
pub fn header ( & self ) -> Result < LayoutVerified < & [ u8 ] , V2_HEADER > > {
406
439
LayoutVerified :: < & [ u8 ] , V2_HEADER > :: new_unaligned_from_prefix (
@@ -509,6 +542,7 @@ impl<'a> Apcb<'a> {
509
542
510
543
pub fn groups ( & self ) -> Result < ApcbIter < ' _ > > {
511
544
Ok ( ApcbIter {
545
+ context : self . context ,
512
546
buf : self . beginning_of_groups ( ) ?,
513
547
remaining_used_size : self . used_size ,
514
548
} )
@@ -529,6 +563,7 @@ impl<'a> Apcb<'a> {
529
563
pub fn groups_mut ( & mut self ) -> Result < ApcbIterMut < ' _ > > {
530
564
let used_size = self . used_size ;
531
565
Ok ( ApcbIterMut {
566
+ context : self . context ,
532
567
buf : & mut * self . beginning_of_groups_mut ( ) ?,
533
568
remaining_used_size : used_size,
534
569
} )
@@ -1030,6 +1065,7 @@ impl<'a> Apcb<'a> {
1030
1065
signature : [ u8 ; 4 ] ,
1031
1066
) -> Result < GroupMutItem < ' _ > > {
1032
1067
// TODO: insert sorted.
1068
+ let context = self . context ;
1033
1069
1034
1070
if !match group_id {
1035
1071
GroupId :: Psp => signature == * b"PSPG" ,
@@ -1090,7 +1126,7 @@ impl<'a> Apcb<'a> {
1090
1126
) ) ?;
1091
1127
let body_len = body. len ( ) ;
1092
1128
1093
- Ok ( GroupMutItem { header, buf : body, used_size : body_len } )
1129
+ Ok ( GroupMutItem { context , header, buf : body, used_size : body_len } )
1094
1130
}
1095
1131
1096
1132
pub ( crate ) fn calculate_checksum (
@@ -1263,7 +1299,8 @@ impl<'a> Apcb<'a> {
1263
1299
) ) ;
1264
1300
}
1265
1301
}
1266
- let result = Self { backing_store : bs, used_size } ;
1302
+ let result =
1303
+ Self { context : options. context ( ) , backing_store : bs, used_size } ;
1267
1304
1268
1305
match result. groups ( ) ?. validate ( ) {
1269
1306
Ok ( _) => { }
0 commit comments