@@ -72,6 +72,16 @@ pub enum NameError {
7272 Invalid ( String , String ) ,
7373}
7474
75+ #[ derive( Clone , Debug , PartialEq , Eq , thiserror:: Error ) ]
76+ pub enum ResetValueError {
77+ #[ error( "Reset value 0x{0:x} doesn't fit in {1} bits" ) ]
78+ ValueTooLarge ( u32 , u32 ) ,
79+ #[ error( "Reset value 0x{0:x} conflicts with mask '{1}'" ) ]
80+ MaskConflict ( u32 , u32 ) ,
81+ #[ error( "Mask value 0x{0:x} doesn't fit in {1} bits" ) ]
82+ MaskTooLarge ( u32 , u32 ) ,
83+ }
84+
7585pub ( crate ) fn is_valid_name ( name : & str ) -> bool {
7686 let mut chars = name. chars ( ) ;
7787 if let Some ( first) = chars. next ( ) {
@@ -96,3 +106,56 @@ pub(crate) fn check_name(name: &str, tag: &str) -> Result<()> {
96106 Err ( NameError :: Invalid ( name. to_string ( ) , tag. to_string ( ) ) . into ( ) )
97107 }
98108}
109+
110+ pub ( crate ) fn check_reset_value (
111+ size : & Option < u32 > ,
112+ value : & Option < u32 > ,
113+ mask : & Option < u32 > ,
114+ ) -> Result < ( ) > {
115+ const MAX_BITS : u32 = u32:: MAX . count_ones ( ) ;
116+
117+ if let ( & Some ( size) , & Some ( value) ) = ( size, value) {
118+ if MAX_BITS - value. leading_zeros ( ) > size {
119+ return Err ( ResetValueError :: ValueTooLarge ( value, size) . into ( ) ) ;
120+ }
121+ }
122+ if let ( & Some ( size) , & Some ( mask) ) = ( size, mask) {
123+ if MAX_BITS - mask. leading_zeros ( ) > size {
124+ return Err ( ResetValueError :: MaskTooLarge ( mask, size) . into ( ) ) ;
125+ }
126+ }
127+ if let ( & Some ( value) , & Some ( mask) ) = ( value, mask) {
128+ if value & mask != value {
129+ return Err ( ResetValueError :: MaskConflict ( value, mask) . into ( ) ) ;
130+ }
131+ }
132+
133+ Ok ( ( ) )
134+ }
135+
136+ #[ cfg( test) ]
137+ mod tests {
138+ use crate :: error:: check_reset_value;
139+
140+ #[ test]
141+ fn test_check_reset_value ( ) {
142+ check_reset_value ( & None , & None , & None ) . unwrap ( ) ;
143+ check_reset_value ( & Some ( 8 ) , & None , & None ) . unwrap ( ) ;
144+ check_reset_value ( & Some ( 8 ) , & None , & Some ( 0xff ) ) . unwrap ( ) ;
145+ check_reset_value ( & Some ( 32 ) , & Some ( 0xfaceface ) , & None ) . unwrap ( ) ;
146+ check_reset_value ( & Some ( 32 ) , & Some ( 0xfaceface ) , & Some ( 0xffffffff ) ) . unwrap ( ) ;
147+
148+ assert ! (
149+ check_reset_value( & Some ( 8 ) , & None , & Some ( 0x100 ) ) . is_err( ) ,
150+ "mask shouldn't fit in size"
151+ ) ;
152+ assert ! (
153+ check_reset_value( & Some ( 1 ) , & Some ( 0x02 ) , & None ) . is_err( ) ,
154+ "reset value shouldn't fit in field"
155+ ) ;
156+ assert ! (
157+ check_reset_value( & Some ( 8 ) , & Some ( 0x80 ) , & Some ( 0x01 ) ) . is_err( ) ,
158+ "value should conflict with mask"
159+ ) ;
160+ }
161+ }
0 commit comments