2929from typing_extensions import Self
3030
3131from .boolean import Boolean
32+ from .exceptions import SSZSerializationError , SSZTypeError , SSZValueError
3233from .ssz_base import SSZModel
3334
3435
@@ -55,13 +56,15 @@ class BaseBitvector(SSZModel):
5556 def _coerce_and_validate (cls , v : Any ) -> tuple [Boolean , ...]:
5657 """Validate and convert input data to typed tuple of Booleans."""
5758 if not hasattr (cls , "LENGTH" ):
58- raise TypeError (f"{ cls .__name__ } must define LENGTH" )
59+ raise SSZTypeError (f"{ cls .__name__ } must define LENGTH" )
5960
6061 if not isinstance (v , (list , tuple )):
6162 v = tuple (v )
6263
6364 if len (v ) != cls .LENGTH :
64- raise ValueError (f"{ cls .__name__ } requires exactly { cls .LENGTH } bits, got { len (v )} " )
65+ raise SSZValueError (
66+ f"{ cls .__name__ } requires exactly { cls .LENGTH } elements, got { len (v )} "
67+ )
6568
6669 return tuple (Boolean (bit ) for bit in v )
6770
@@ -86,10 +89,12 @@ def deserialize(cls, stream: IO[bytes], scope: int) -> Self:
8689 """Read SSZ bytes from a stream and return an instance."""
8790 expected_len = cls .get_byte_length ()
8891 if scope != expected_len :
89- raise ValueError (f"{ cls .__name__ } : expected { expected_len } bytes, got { scope } " )
92+ raise SSZSerializationError (
93+ f"{ cls .__name__ } : expected { expected_len } bytes, got { scope } "
94+ )
9095 data = stream .read (scope )
9196 if len (data ) != scope :
92- raise IOError (f"Expected { scope } bytes, got { len (data )} " )
97+ raise SSZSerializationError (f"{ cls . __name__ } : expected { scope } bytes, got { len (data )} " )
9398 return cls .decode_bytes (data )
9499
95100 def encode_bytes (self ) -> bytes :
@@ -115,7 +120,7 @@ def decode_bytes(cls, data: bytes) -> Self:
115120 """
116121 expected = cls .get_byte_length ()
117122 if len (data ) != expected :
118- raise ValueError (f"{ cls .__name__ } : expected { expected } bytes, got { len (data )} " )
123+ raise SSZValueError (f"{ cls .__name__ } : expected { expected } bytes, got { len (data )} " )
119124
120125 bits = tuple (Boolean ((data [i // 8 ] >> (i % 8 )) & 1 ) for i in range (cls .LENGTH ))
121126 return cls (data = bits )
@@ -144,19 +149,19 @@ class BaseBitlist(SSZModel):
144149 def _coerce_and_validate (cls , v : Any ) -> tuple [Boolean , ...]:
145150 """Validate and convert input to a tuple of Boolean elements."""
146151 if not hasattr (cls , "LIMIT" ):
147- raise TypeError (f"{ cls .__name__ } must define LIMIT" )
152+ raise SSZTypeError (f"{ cls .__name__ } must define LIMIT" )
148153
149154 # Handle various input types
150155 if isinstance (v , (list , tuple )):
151156 elements = v
152157 elif hasattr (v , "__iter__" ) and not isinstance (v , (str , bytes )):
153158 elements = list (v )
154159 else :
155- raise TypeError (f"Bitlist data must be iterable, got { type (v )} " )
160+ raise SSZTypeError (f"Expected iterable, got { type (v ). __name__ } " )
156161
157162 # Check limit
158163 if len (elements ) > cls .LIMIT :
159- raise ValueError (f"{ cls .__name__ } cannot exceed { cls .LIMIT } bits , got { len (elements )} " )
164+ raise SSZValueError (f"{ cls .__name__ } exceeds limit of { cls .LIMIT } , got { len (elements )} " )
160165
161166 return tuple (Boolean (bit ) for bit in elements )
162167
@@ -197,8 +202,8 @@ def is_fixed_size(cls) -> bool:
197202
198203 @classmethod
199204 def get_byte_length (cls ) -> int :
200- """Lists are variable-size, so this raises a TypeError ."""
201- raise TypeError (f"{ cls .__name__ } is variable-size" )
205+ """Lists are variable-size, so this raises an SSZTypeError ."""
206+ raise SSZTypeError (f"{ cls .__name__ } : variable-size bitlist has no fixed byte length " )
202207
203208 def serialize (self , stream : IO [bytes ]) -> int :
204209 """Write SSZ bytes to a binary stream."""
@@ -211,7 +216,7 @@ def deserialize(cls, stream: IO[bytes], scope: int) -> Self:
211216 """Read SSZ bytes from a stream and return an instance."""
212217 data = stream .read (scope )
213218 if len (data ) != scope :
214- raise IOError (f"Expected { scope } bytes, got { len (data )} " )
219+ raise SSZSerializationError (f"{ cls . __name__ } : expected { scope } bytes, got { len (data )} " )
215220 return cls .decode_bytes (data )
216221
217222 def encode_bytes (self ) -> bytes :
@@ -254,7 +259,7 @@ def decode_bytes(cls, data: bytes) -> Self:
254259 the last data bit. All bits after the delimiter are assumed to be 0.
255260 """
256261 if len (data ) == 0 :
257- raise ValueError ( "Cannot decode empty bytes to Bitlist " )
262+ raise SSZSerializationError ( f" { cls . __name__ } : cannot decode empty bytes" )
258263
259264 # Find the position of the delimiter bit (rightmost 1).
260265 delimiter_pos = None
@@ -267,12 +272,12 @@ def decode_bytes(cls, data: bytes) -> Self:
267272 break
268273
269274 if delimiter_pos is None :
270- raise ValueError ( "No delimiter bit found in Bitlist data " )
275+ raise SSZSerializationError ( f" { cls . __name__ } : no delimiter bit found" )
271276
272277 # Extract data bits (everything before the delimiter).
273278 num_bits = delimiter_pos
274279 if num_bits > cls .LIMIT :
275- raise ValueError (f"{ cls .__name__ } decoded length { num_bits } exceeds limit { cls .LIMIT } " )
280+ raise SSZValueError (f"{ cls .__name__ } exceeds limit of { cls .LIMIT } , got { num_bits } " )
276281
277282 bits = tuple (Boolean ((data [i // 8 ] >> (i % 8 )) & 1 ) for i in range (num_bits ))
278283 return cls (data = bits )
0 commit comments