1
1
use crate :: flasher:: Command ;
2
2
use crate :: image_format:: ImageFormatId ;
3
+ use crate :: partition_table:: { SubType , Type } ;
3
4
use crate :: Chip ;
4
- use csv:: Position ;
5
5
use miette:: { Diagnostic , SourceOffset , SourceSpan } ;
6
6
use slip_codec:: Error as SlipError ;
7
7
use std:: fmt:: { Display , Formatter } ;
@@ -266,32 +266,52 @@ impl<T> ResultExt for Result<T, Error> {
266
266
}
267
267
}
268
268
269
+ #[ derive( Debug , Error , Diagnostic ) ]
270
+ pub enum PartitionTableError {
271
+ #[ error( transparent) ]
272
+ #[ diagnostic( transparent) ]
273
+ Csv ( #[ from] CSVError ) ,
274
+ #[ error( transparent) ]
275
+ #[ diagnostic( transparent) ]
276
+ Overlapping ( #[ from] OverlappingPartitionsError ) ,
277
+ #[ error( transparent) ]
278
+ #[ diagnostic( transparent) ]
279
+ Duplicate ( #[ from] DuplicatePartitionsError ) ,
280
+ #[ error( transparent) ]
281
+ #[ diagnostic( transparent) ]
282
+ InvalidSubType ( #[ from] InvalidSubTypeError ) ,
283
+ #[ error( transparent) ]
284
+ #[ diagnostic( transparent) ]
285
+ UnalignedPartitionError ( #[ from] UnalignedPartitionError ) ,
286
+ }
287
+
269
288
#[ derive( Debug , Error , Diagnostic ) ]
270
289
#[ error( "Malformed partition table" ) ]
271
290
#[ diagnostic(
272
- code( espflash:: mallformed_partition_table ) ,
273
- help( "See the espressif documentation for information on the partition table format:
291
+ code( espflash:: partition_table :: mallformed ) ,
292
+ help( "{} See the espressif documentation for information on the partition table format:
274
293
275
- https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html#creating-custom-tables" )
294
+ https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html#creating-custom-tables" , self . help )
276
295
) ]
277
- pub struct PartitionTableError {
296
+ pub struct CSVError {
278
297
#[ source_code]
279
298
source : String ,
280
299
#[ label( "{}" , self . hint) ]
281
300
err_span : SourceSpan ,
282
301
hint : String ,
283
302
#[ source]
284
303
error : csv:: Error ,
304
+ help : String ,
285
305
}
286
306
287
- impl PartitionTableError {
307
+ impl CSVError {
288
308
pub fn new ( error : csv:: Error , source : String ) -> Self {
289
- let err_pos = match error. kind ( ) {
290
- csv:: ErrorKind :: Deserialize { pos : Some ( pos) , .. } => pos. clone ( ) ,
291
- csv:: ErrorKind :: UnequalLengths { pos : Some ( pos) , .. } => pos. clone ( ) ,
292
- _ => Position :: new ( ) ,
309
+ let err_line = match error. kind ( ) {
310
+ csv:: ErrorKind :: Deserialize { pos : Some ( pos) , .. } => pos. line ( ) ,
311
+ csv:: ErrorKind :: UnequalLengths { pos : Some ( pos) , .. } => pos. line ( ) ,
312
+ _ => 0 ,
293
313
} ;
294
- let hint = match error. kind ( ) {
314
+ let mut hint = match error. kind ( ) {
295
315
csv:: ErrorKind :: Deserialize { err, .. } => err. to_string ( ) ,
296
316
csv:: ErrorKind :: UnequalLengths {
297
317
expected_len, len, ..
@@ -301,27 +321,135 @@ impl PartitionTableError {
301
321
) ,
302
322
_ => String :: new ( ) ,
303
323
} ;
324
+ let mut help = String :: new ( ) ;
325
+
326
+ // string matching is fragile but afaik there is no better way in this case
327
+ // and if it does break the error is still not bad
328
+ if hint == "data did not match any variant of untagged enum SubType" {
329
+ hint = "Unknown sub-type" . into ( ) ;
330
+ help = format ! (
331
+ "the following sub-types are supported:
332
+ {} for data partitions
333
+ {} for app partitions\n \n " ,
334
+ Type :: Data . subtype_hint( ) ,
335
+ Type :: App . subtype_hint( )
336
+ )
337
+ }
304
338
305
- // since csv doesn't give us the position in the line the error occurs, we highlight the entire line
306
- let line_length = source
307
- . lines ( )
308
- . nth ( err_pos. line ( ) as usize - 1 )
309
- . unwrap ( )
310
- . len ( )
311
- . into ( ) ;
312
- let err_span = SourceSpan :: new ( pos_to_offset ( err_pos) , line_length) ;
339
+ let err_span = line_to_span ( & source, err_line as usize ) ;
313
340
314
- PartitionTableError {
341
+ CSVError {
315
342
source,
316
343
err_span,
317
344
hint,
318
345
error,
346
+ help,
347
+ }
348
+ }
349
+ }
350
+
351
+ /// since csv doesn't give us the position in the line the error occurs, we highlight the entire line
352
+ ///
353
+ /// line starts at 1
354
+ fn line_to_span ( source : & str , line : usize ) -> SourceSpan {
355
+ let line_length = source. lines ( ) . nth ( line - 1 ) . unwrap ( ) . len ( ) . into ( ) ;
356
+ SourceSpan :: new ( SourceOffset :: from_location ( source, line, 2 ) , line_length)
357
+ }
358
+
359
+ #[ derive( Debug , Error , Diagnostic ) ]
360
+ #[ error( "Overlapping partitions" ) ]
361
+ #[ diagnostic( code( espflash:: partition_table:: overlapping) ) ]
362
+ pub struct OverlappingPartitionsError {
363
+ #[ source_code]
364
+ source_code : String ,
365
+ #[ label( "This partition" ) ]
366
+ partition1_span : SourceSpan ,
367
+ #[ label( "overlaps with this partition" ) ]
368
+ partition2_span : SourceSpan ,
369
+ }
370
+
371
+ impl OverlappingPartitionsError {
372
+ pub fn new ( source : & str , partition1_line : usize , partition2_line : usize ) -> Self {
373
+ OverlappingPartitionsError {
374
+ source_code : source. into ( ) ,
375
+ partition1_span : line_to_span ( source, partition1_line) ,
376
+ partition2_span : line_to_span ( source, partition2_line) ,
319
377
}
320
378
}
321
379
}
322
380
323
- fn pos_to_offset ( pos : Position ) -> SourceOffset {
324
- ( pos. byte ( ) as usize ) . into ( )
381
+ #[ derive( Debug , Error , Diagnostic ) ]
382
+ #[ error( "Duplicate partitions" ) ]
383
+ #[ diagnostic( code( espflash:: partition_table:: duplicate) ) ]
384
+ pub struct DuplicatePartitionsError {
385
+ #[ source_code]
386
+ source_code : String ,
387
+ #[ label( "This partition" ) ]
388
+ partition1_span : SourceSpan ,
389
+ #[ label( "has the same {} as this partition" , self . ty) ]
390
+ partition2_span : SourceSpan ,
391
+ ty : & ' static str ,
392
+ }
393
+
394
+ impl DuplicatePartitionsError {
395
+ pub fn new (
396
+ source : & str ,
397
+ partition1_line : usize ,
398
+ partition2_line : usize ,
399
+ ty : & ' static str ,
400
+ ) -> Self {
401
+ DuplicatePartitionsError {
402
+ source_code : source. into ( ) ,
403
+ partition1_span : line_to_span ( source, partition1_line) ,
404
+ partition2_span : line_to_span ( source, partition2_line) ,
405
+ ty,
406
+ }
407
+ }
408
+ }
409
+
410
+ #[ derive( Debug , Error , Diagnostic ) ]
411
+ #[ error( "Invalid subtype for type" ) ]
412
+ #[ diagnostic(
413
+ code( espflash:: partition_table:: invalid_type) ,
414
+ help( "'{}' supports the following subtypes: {}" , self . ty, self . ty. subtype_hint( ) )
415
+ ) ]
416
+ pub struct InvalidSubTypeError {
417
+ #[ source_code]
418
+ source_code : String ,
419
+ #[ label( "'{}' is not a valid subtype for '{}'" , self . sub_type, self . ty) ]
420
+ span : SourceSpan ,
421
+ ty : Type ,
422
+ sub_type : SubType ,
423
+ }
424
+
425
+ impl InvalidSubTypeError {
426
+ pub fn new ( source : & str , line : usize , ty : Type , sub_type : SubType ) -> Self {
427
+ InvalidSubTypeError {
428
+ source_code : source. into ( ) ,
429
+ span : line_to_span ( source, line) ,
430
+ ty,
431
+ sub_type,
432
+ }
433
+ }
434
+ }
435
+
436
+ #[ derive( Debug , Error , Diagnostic ) ]
437
+ #[ error( "Unaligned partition" ) ]
438
+ #[ diagnostic( code( espflash:: partition_table:: unaligned) ) ]
439
+ pub struct UnalignedPartitionError {
440
+ #[ source_code]
441
+ source_code : String ,
442
+ #[ label( "App partition is not aligned to 64k (0x10000)" ) ]
443
+ span : SourceSpan ,
444
+ }
445
+
446
+ impl UnalignedPartitionError {
447
+ pub fn new ( source : & str , line : usize ) -> Self {
448
+ UnalignedPartitionError {
449
+ source_code : source. into ( ) ,
450
+ span : line_to_span ( source, line) ,
451
+ }
452
+ }
325
453
}
326
454
327
455
#[ derive( Debug , Error ) ]
0 commit comments