@@ -19,9 +19,58 @@ use core::{
1919 cmp,
2020 fmt:: { self , Display } ,
2121} ;
22+ use std:: vec:: Vec ;
23+
24+ /// A non-empty list of [`Error`]s.
25+ pub struct ErrorList < ' ctx > {
26+ ctx : ErrorContext < ' ctx > ,
27+ errors : Vec < Error > ,
28+ }
29+
30+ impl < ' ctx > ErrorList < ' ctx > {
31+ /// Creates a new [`ErrorList`].
32+ ///
33+ /// # Panics
34+ ///
35+ /// If `errors` is empty.
36+ fn new ( ctx : ErrorContext < ' ctx > , errors : Vec < Error > ) -> Self {
37+ assert ! ( !errors. is_empty( ) ) ;
38+ Self { ctx, errors }
39+ }
40+ }
41+
42+ impl ErrorList < ' _ > {
43+ /// Returns `true` if `self` contains at least one [`Error`].
44+ fn has_errors ( & self ) -> bool {
45+ !self . errors . is_empty ( )
46+ }
47+
48+ /// Returns the number of [`Error`]s in `self`.
49+ fn len_errors ( & self ) -> usize {
50+ self . errors . len ( )
51+ }
52+ }
53+
54+ impl Display for ErrorList < ' _ > {
55+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
56+ if !self . has_errors ( ) {
57+ return writeln ! ( f, "all checked Wasmi translation invariants are uphold" ) ;
58+ }
59+ writeln ! (
60+ f,
61+ "encountered {} broken invariants for Wasmi translation:" ,
62+ self . len_errors( )
63+ ) ?;
64+ let ctx = self . ctx ;
65+ for ( n, error) in self . errors . iter ( ) . cloned ( ) . enumerate ( ) {
66+ write ! ( f, "error({n}): {}" , ErrorWithContext { ctx, error } ) ?;
67+ }
68+ Ok ( ( ) )
69+ }
70+ }
2271
2372/// An error describing a broken Wasmi translation invariant.
24- #[ derive( Debug ) ]
73+ #[ derive( Debug , Clone ) ]
2574pub struct Error {
2675 /// The erraneous `Instruction` index.
2776 instr : Instr ,
@@ -30,7 +79,7 @@ pub struct Error {
3079}
3180
3281/// The reason behind a broken Wasmi translation invariant.
33- #[ derive( Debug ) ]
82+ #[ derive( Debug , Clone ) ]
3483pub enum Reason {
3584 InvalidRegister {
3685 /// The invalid `Reg`.
@@ -216,6 +265,7 @@ pub struct ErrorWithContext<'ctx> {
216265}
217266
218267/// A context to populate an [`Error`] with more information for its [`Display`] implementation.
268+ #[ derive( Copy , Clone ) ]
219269pub struct ErrorContext < ' ctx > {
220270 /// The underlying Wasmi function translator that has already finished its job.
221271 translator : & ' ctx FuncTranslator ,
@@ -286,15 +336,8 @@ impl ErrorWithContext<'_> {
286336/// # Errors
287337///
288338/// If a Wasmi translation invariant is broken.
289- pub fn verify_translation_invariants ( translator : & FuncTranslator ) -> Result < ( ) , ErrorWithContext > {
290- let checker = TranslationInvariantsChecker { translator } ;
291- match checker. verify_translation_invariants ( ) {
292- Ok ( _) => Ok ( ( ) ) ,
293- Err ( error) => {
294- let ctx = ErrorContext { translator } ;
295- Err ( ErrorWithContext { ctx, error } )
296- }
297- }
339+ pub fn verify_translation_invariants ( translator : & FuncTranslator ) -> Result < ( ) , ErrorList > {
340+ TranslationInvariantsChecker { translator } . verify_translation_invariants ( )
298341}
299342
300343/// Encapsulates state required for translation invariants checking.
@@ -303,15 +346,25 @@ struct TranslationInvariantsChecker<'translator> {
303346 translator : & ' translator FuncTranslator ,
304347}
305348
306- impl TranslationInvariantsChecker < ' _ > {
349+ impl < ' translator > TranslationInvariantsChecker < ' translator > {
307350 /// Checks if the invariants of Wasmi function translation are uphold.
308351 ///
309352 /// Read more here: [`verify_translation_invariants`]
310353 ///
311354 /// # Errors
312355 ///
313356 /// If a Wasmi translation invariant is broken.
314- fn verify_translation_invariants ( & self ) -> Result < ( ) , Error > {
315- todo ! ( )
357+ fn verify_translation_invariants ( & self ) -> Result < ( ) , ErrorList < ' translator > > {
358+ let errors = Vec :: new ( ) ;
359+ // TODO: perform invariant checking
360+ if errors. is_empty ( ) {
361+ return Ok ( ( ) ) ;
362+ }
363+ Err ( ErrorList :: new (
364+ ErrorContext {
365+ translator : self . translator ,
366+ } ,
367+ errors,
368+ ) )
316369 }
317370}
0 commit comments