faster-eth-abi 5.2.25__cp311-cp311-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. faster_eth_abi/__init__.py +17 -0
  2. faster_eth_abi/_codec.cpython-311-x86_64-linux-musl.so +0 -0
  3. faster_eth_abi/_codec.py +83 -0
  4. faster_eth_abi/_decoding.cpython-311-x86_64-linux-musl.so +0 -0
  5. faster_eth_abi/_decoding.py +371 -0
  6. faster_eth_abi/_encoding.cpython-311-x86_64-linux-musl.so +0 -0
  7. faster_eth_abi/_encoding.py +514 -0
  8. faster_eth_abi/_grammar.cpython-311-x86_64-linux-musl.so +0 -0
  9. faster_eth_abi/_grammar.py +389 -0
  10. faster_eth_abi/abi.cpython-311-x86_64-linux-musl.so +0 -0
  11. faster_eth_abi/abi.py +17 -0
  12. faster_eth_abi/base.py +45 -0
  13. faster_eth_abi/codec.py +2809 -0
  14. faster_eth_abi/constants.cpython-311-x86_64-linux-musl.so +0 -0
  15. faster_eth_abi/constants.py +7 -0
  16. faster_eth_abi/decoding.py +555 -0
  17. faster_eth_abi/encoding.py +738 -0
  18. faster_eth_abi/exceptions.cpython-311-x86_64-linux-musl.so +0 -0
  19. faster_eth_abi/exceptions.py +127 -0
  20. faster_eth_abi/from_type_str.cpython-311-x86_64-linux-musl.so +0 -0
  21. faster_eth_abi/from_type_str.py +141 -0
  22. faster_eth_abi/grammar.py +179 -0
  23. faster_eth_abi/io.cpython-311-x86_64-linux-musl.so +0 -0
  24. faster_eth_abi/io.py +137 -0
  25. faster_eth_abi/packed.cpython-311-x86_64-linux-musl.so +0 -0
  26. faster_eth_abi/packed.py +19 -0
  27. faster_eth_abi/py.typed +0 -0
  28. faster_eth_abi/registry.py +758 -0
  29. faster_eth_abi/tools/__init__.cpython-311-x86_64-linux-musl.so +0 -0
  30. faster_eth_abi/tools/__init__.py +3 -0
  31. faster_eth_abi/tools/_strategies.cpython-311-x86_64-linux-musl.so +0 -0
  32. faster_eth_abi/tools/_strategies.py +247 -0
  33. faster_eth_abi/typing.py +4627 -0
  34. faster_eth_abi/utils/__init__.cpython-311-x86_64-linux-musl.so +0 -0
  35. faster_eth_abi/utils/__init__.py +0 -0
  36. faster_eth_abi/utils/localcontext.cpython-311-x86_64-linux-musl.so +0 -0
  37. faster_eth_abi/utils/localcontext.py +49 -0
  38. faster_eth_abi/utils/numeric.cpython-311-x86_64-linux-musl.so +0 -0
  39. faster_eth_abi/utils/numeric.py +117 -0
  40. faster_eth_abi/utils/padding.cpython-311-x86_64-linux-musl.so +0 -0
  41. faster_eth_abi/utils/padding.py +22 -0
  42. faster_eth_abi/utils/string.cpython-311-x86_64-linux-musl.so +0 -0
  43. faster_eth_abi/utils/string.py +19 -0
  44. faster_eth_abi/utils/validation.cpython-311-x86_64-linux-musl.so +0 -0
  45. faster_eth_abi/utils/validation.py +18 -0
  46. faster_eth_abi-5.2.25.dist-info/METADATA +134 -0
  47. faster_eth_abi-5.2.25.dist-info/RECORD +50 -0
  48. faster_eth_abi-5.2.25.dist-info/WHEEL +5 -0
  49. faster_eth_abi-5.2.25.dist-info/top_level.txt +2 -0
  50. faster_eth_abi__mypyc.cpython-311-x86_64-linux-musl.so +0 -0
@@ -0,0 +1,7 @@
1
+ from typing import (
2
+ Final,
3
+ )
4
+
5
+ TT256: Final = 2**256
6
+ TT256M1: Final = 2**256 - 1
7
+ TT255: Final = 2**255
@@ -0,0 +1,555 @@
1
+ """Classes for ABI decoding logic.
2
+
3
+ Implements classes and functions for deserializing binary data into Python values
4
+ according to ABI type specifications.
5
+ """
6
+ import abc
7
+ import decimal
8
+ from functools import (
9
+ cached_property,
10
+ lru_cache,
11
+ )
12
+ from types import (
13
+ MethodType,
14
+ )
15
+ from typing import (
16
+ Any,
17
+ Callable,
18
+ Final,
19
+ Generic,
20
+ Optional,
21
+ Tuple,
22
+ TypeVar,
23
+ Union,
24
+ final,
25
+ )
26
+
27
+ from eth_typing import (
28
+ HexAddress,
29
+ )
30
+ from faster_eth_utils import (
31
+ big_endian_to_int,
32
+ to_normalized_address,
33
+ )
34
+
35
+ from faster_eth_abi._decoding import (
36
+ decode_dynamic_array,
37
+ decode_head_tail,
38
+ decode_signed_fixed,
39
+ decode_sized_array,
40
+ decode_string,
41
+ decode_tuple,
42
+ decode_unsigned_fixed,
43
+ decoder_fn_boolean,
44
+ get_value_byte_size,
45
+ read_bytestring_from_stream,
46
+ read_fixed_byte_size_data_from_stream,
47
+ split_data_and_padding_fixed_byte_size,
48
+ validate_padding_bytes_fixed_byte_size,
49
+ validate_padding_bytes_signed_integer,
50
+ validate_pointers_array,
51
+ )
52
+ from faster_eth_abi.base import (
53
+ BaseCoder,
54
+ )
55
+ from faster_eth_abi.exceptions import (
56
+ NonEmptyPaddingBytes,
57
+ )
58
+ from faster_eth_abi.from_type_str import (
59
+ parse_tuple_type_str,
60
+ parse_type_str,
61
+ )
62
+ from faster_eth_abi.io import (
63
+ ContextFramesBytesIO,
64
+ )
65
+ from faster_eth_abi.typing import (
66
+ T,
67
+ )
68
+ from faster_eth_abi.utils.numeric import (
69
+ TEN,
70
+ )
71
+
72
+ TByteStr = TypeVar("TByteStr", bytes, str)
73
+
74
+
75
+ class BaseDecoder(BaseCoder, Generic[T], metaclass=abc.ABCMeta):
76
+ """
77
+ Base class for all decoder classes. Subclass this if you want to define a
78
+ custom decoder class. Subclasses must also implement
79
+ :any:`BaseCoder.from_type_str`.
80
+ """
81
+
82
+ strict = True
83
+
84
+ @abc.abstractmethod
85
+ def decode(self, stream: ContextFramesBytesIO) -> T: # pragma: no cover
86
+ """
87
+ Decodes the given stream of bytes into a python value. Should raise
88
+ :any:`exceptions.DecodingError` if a python value cannot be decoded
89
+ from the given byte stream.
90
+ """
91
+
92
+ def __call__(self, stream: ContextFramesBytesIO) -> T:
93
+ return self.decode(stream)
94
+
95
+
96
+ class HeadTailDecoder(BaseDecoder[T]):
97
+ """
98
+ Decoder for a dynamic element of a dynamic container (a dynamic array, or a sized
99
+ array or tuple that contains dynamic elements). A dynamic element consists of a
100
+ pointer, aka offset, which is located in the head section of the encoded container,
101
+ and the actual value, which is located in the tail section of the encoding.
102
+ """
103
+
104
+ is_dynamic = True
105
+
106
+ def __init__(
107
+ self,
108
+ tail_decoder: Union[ # type: ignore [type-var]
109
+ "HeadTailDecoder[T]",
110
+ "SizedArrayDecoder[T]",
111
+ "DynamicArrayDecoder[T]",
112
+ "ByteStringDecoder[T]",
113
+ ],
114
+ ) -> None:
115
+ super().__init__()
116
+
117
+ if tail_decoder is None:
118
+ raise ValueError("No `tail_decoder` set")
119
+
120
+ self.tail_decoder: Final = tail_decoder
121
+
122
+ def decode(self, stream: ContextFramesBytesIO) -> T:
123
+ return decode_head_tail(self, stream)
124
+
125
+ __call__ = decode
126
+
127
+
128
+ class TupleDecoder(BaseDecoder[tuple[T, ...]]):
129
+ decoders: Tuple[BaseDecoder[T], ...] = ()
130
+
131
+ def __init__(self, decoders: Tuple[BaseDecoder[T], ...]) -> None:
132
+ super().__init__()
133
+
134
+ self.decoders = decoders = tuple(
135
+ HeadTailDecoder(tail_decoder=d) if getattr(d, "is_dynamic", False) else d
136
+ for d in decoders
137
+ )
138
+
139
+ self.is_dynamic = any(getattr(d, "is_dynamic", False) for d in decoders)
140
+ self.len_of_head = sum(
141
+ getattr(decoder, "array_size", 1) for decoder in decoders
142
+ )
143
+ self._is_head_tail = tuple(
144
+ isinstance(decoder, HeadTailDecoder) for decoder in decoders
145
+ )
146
+ self._no_head_tail = not any(self._is_head_tail)
147
+
148
+ def validate(self) -> None:
149
+ super().validate()
150
+
151
+ if self.decoders is None:
152
+ raise ValueError("No `decoders` set")
153
+
154
+ @final
155
+ def validate_pointers(self, stream: ContextFramesBytesIO) -> None:
156
+ raise NotImplementedError("didnt call __init__")
157
+
158
+ def decode(self, stream: ContextFramesBytesIO) -> Tuple[T, ...]:
159
+ return decode_tuple(self, stream)
160
+
161
+ __call__ = decode
162
+
163
+ @parse_tuple_type_str
164
+ def from_type_str(cls, abi_type, registry):
165
+ decoders = tuple(
166
+ registry.get_decoder(c.to_type_str()) for c in abi_type.components
167
+ )
168
+
169
+ return cls(decoders=decoders)
170
+
171
+
172
+ class SingleDecoder(BaseDecoder[T]):
173
+ decoder_fn = None
174
+
175
+ def validate(self) -> None:
176
+ super().validate()
177
+
178
+ if self.decoder_fn is None:
179
+ raise ValueError("No `decoder_fn` set")
180
+
181
+ def validate_padding_bytes(self, value: Any, padding_bytes: bytes) -> None:
182
+ raise NotImplementedError("Must be implemented by subclasses")
183
+
184
+ def decode(self, stream: ContextFramesBytesIO) -> T:
185
+ raw_data = self.read_data_from_stream(stream)
186
+ data, padding_bytes = self.split_data_and_padding(raw_data)
187
+ value = self.decoder_fn(data) # type: ignore [misc]
188
+ self.validate_padding_bytes(value, padding_bytes)
189
+
190
+ return value
191
+
192
+ __call__ = decode
193
+
194
+ def read_data_from_stream(self, stream: ContextFramesBytesIO) -> bytes:
195
+ raise NotImplementedError("Must be implemented by subclasses")
196
+
197
+ def split_data_and_padding(self, raw_data: bytes) -> Tuple[bytes, bytes]:
198
+ return raw_data, b""
199
+
200
+
201
+ class BaseArrayDecoder(BaseDecoder[Tuple[T, ...]]):
202
+ item_decoder: BaseDecoder[T] = None
203
+
204
+ def __init__(self, **kwargs: Any) -> None:
205
+ super().__init__(**kwargs)
206
+
207
+ # Use a head-tail decoder to decode dynamic elements
208
+ item_decoder = self.item_decoder
209
+ if item_decoder.is_dynamic:
210
+ self.item_decoder = HeadTailDecoder(tail_decoder=item_decoder)
211
+ self.validate_pointers = MethodType(validate_pointers_array, self)
212
+ else:
213
+
214
+ def noop(stream: ContextFramesBytesIO, array_size: int) -> None:
215
+ ...
216
+
217
+ self.validate_pointers = noop
218
+
219
+ def decode(self, stream: ContextFramesBytesIO) -> Tuple[T, ...]:
220
+ raise NotImplementedError # this is a type stub
221
+
222
+ def validate(self) -> None:
223
+ super().validate()
224
+
225
+ if self.item_decoder is None:
226
+ raise ValueError("No `item_decoder` set")
227
+
228
+ @parse_type_str(with_arrlist=True)
229
+ def from_type_str(cls, abi_type, registry):
230
+ item_decoder = registry.get_decoder(abi_type.item_type.to_type_str())
231
+
232
+ array_spec = abi_type.arrlist[-1]
233
+ if len(array_spec) == 1:
234
+ # If array dimension is fixed
235
+ return SizedArrayDecoder(
236
+ array_size=array_spec[0],
237
+ item_decoder=item_decoder,
238
+ )
239
+ else:
240
+ # If array dimension is dynamic
241
+ return DynamicArrayDecoder(item_decoder=item_decoder)
242
+
243
+ def validate_pointers(self, stream: ContextFramesBytesIO, array_size: int) -> None:
244
+ """
245
+ Verify that all pointers point to a valid location in the stream.
246
+ """
247
+ validate_pointers_array(self, stream, array_size)
248
+
249
+
250
+ class SizedArrayDecoder(BaseArrayDecoder[T]):
251
+ array_size: int = None
252
+
253
+ def __init__(self, **kwargs: Any) -> None:
254
+ super().__init__(**kwargs)
255
+
256
+ self.is_dynamic = self.item_decoder.is_dynamic
257
+
258
+ def decode(self, stream: ContextFramesBytesIO) -> Tuple[T, ...]:
259
+ return decode_sized_array(self, stream)
260
+
261
+ __call__ = decode
262
+
263
+
264
+ class DynamicArrayDecoder(BaseArrayDecoder[T]):
265
+ # Dynamic arrays are always dynamic, regardless of their elements
266
+ is_dynamic = True
267
+
268
+ def decode(self, stream: ContextFramesBytesIO) -> Tuple[T, ...]:
269
+ return decode_dynamic_array(self, stream)
270
+
271
+ __call__ = decode
272
+
273
+
274
+ class FixedByteSizeDecoder(SingleDecoder[T]):
275
+ decoder_fn: Callable[[bytes], T] = None
276
+ value_bit_size: int = None
277
+ data_byte_size: int = None
278
+ is_big_endian: bool = None
279
+
280
+ def __init__(self, **kwargs: Any) -> None:
281
+ super().__init__(**kwargs)
282
+
283
+ self.read_data_from_stream = MethodType(
284
+ read_fixed_byte_size_data_from_stream, self
285
+ )
286
+ self.split_data_and_padding = MethodType(
287
+ split_data_and_padding_fixed_byte_size, self
288
+ )
289
+ self._get_value_byte_size = MethodType(get_value_byte_size, self)
290
+
291
+ # Only assign validate_padding_bytes if not overridden in subclass
292
+ if type(self).validate_padding_bytes is SingleDecoder.validate_padding_bytes:
293
+ self.validate_padding_bytes = MethodType(
294
+ validate_padding_bytes_fixed_byte_size, self
295
+ )
296
+
297
+ def validate(self) -> None:
298
+ super().validate()
299
+
300
+ value_bit_size = self.value_bit_size
301
+ if value_bit_size is None:
302
+ raise ValueError("`value_bit_size` may not be None")
303
+ data_byte_size = self.data_byte_size
304
+ if data_byte_size is None:
305
+ raise ValueError("`data_byte_size` may not be None")
306
+ if self.decoder_fn is None:
307
+ raise ValueError("`decoder_fn` may not be None")
308
+ if self.is_big_endian is None:
309
+ raise ValueError("`is_big_endian` may not be None")
310
+
311
+ if value_bit_size % 8 != 0:
312
+ raise ValueError(
313
+ f"Invalid value bit size: {value_bit_size}. Must be a multiple of 8"
314
+ )
315
+
316
+ if value_bit_size > data_byte_size * 8:
317
+ raise ValueError("Value byte size exceeds data size")
318
+
319
+ def read_data_from_stream(self, stream: ContextFramesBytesIO) -> bytes:
320
+ raise NotImplementedError("didnt call __init__")
321
+
322
+ def split_data_and_padding(self, raw_data: bytes) -> Tuple[bytes, bytes]:
323
+ raise NotImplementedError("didnt call __init__")
324
+
325
+ # This is unused, but it is kept in to preserve the eth-abi api
326
+ def _get_value_byte_size(self) -> int:
327
+ raise NotImplementedError("didnt call __init__")
328
+
329
+
330
+ class Fixed32ByteSizeDecoder(FixedByteSizeDecoder[T]):
331
+ data_byte_size = 32
332
+
333
+
334
+ class BooleanDecoder(Fixed32ByteSizeDecoder[bool]):
335
+ value_bit_size = 8
336
+ is_big_endian = True
337
+
338
+ decoder_fn = staticmethod(decoder_fn_boolean)
339
+
340
+ @parse_type_str("bool")
341
+ def from_type_str(cls, abi_type, registry):
342
+ return cls()
343
+
344
+
345
+ class AddressDecoder(Fixed32ByteSizeDecoder[HexAddress]):
346
+ value_bit_size = 20 * 8
347
+ is_big_endian = True
348
+ decoder_fn = staticmethod(to_normalized_address)
349
+
350
+ @parse_type_str("address")
351
+ def from_type_str(cls, abi_type, registry):
352
+ return cls()
353
+
354
+
355
+ #
356
+ # Unsigned Integer Decoders
357
+ #
358
+ class UnsignedIntegerDecoder(Fixed32ByteSizeDecoder[int]):
359
+ decoder_fn: "staticmethod[[bytes], int]" = staticmethod(big_endian_to_int)
360
+ is_big_endian = True
361
+
362
+ @parse_type_str("uint")
363
+ def from_type_str(cls, abi_type, registry):
364
+ return cls(value_bit_size=abi_type.sub)
365
+
366
+
367
+ decode_uint_256 = UnsignedIntegerDecoder(value_bit_size=256)
368
+
369
+
370
+ class UnsignedIntegerDecoderCached(UnsignedIntegerDecoder):
371
+ decoder_fn: Callable[[bytes], int]
372
+ maxsize: Final[Optional[int]]
373
+
374
+ def __init__(self, maxsize: Optional[int] = None, **kwargs: Any) -> None:
375
+ super().__init__(**kwargs)
376
+ self.maxsize = maxsize
377
+ self.decoder_fn = lru_cache(maxsize=maxsize)(self.decoder_fn)
378
+
379
+
380
+ #
381
+ # Signed Integer Decoders
382
+ #
383
+ class SignedIntegerDecoder(Fixed32ByteSizeDecoder[int]):
384
+ is_big_endian = True
385
+
386
+ def __init__(self, **kwargs: Any) -> None:
387
+ super().__init__(**kwargs)
388
+
389
+ # Only assign validate_padding_bytes if not overridden in subclass
390
+ if (
391
+ type(self).validate_padding_bytes
392
+ is SignedIntegerDecoder.validate_padding_bytes
393
+ ):
394
+ self.validate_padding_bytes = MethodType(
395
+ validate_padding_bytes_signed_integer, self
396
+ )
397
+
398
+ @cached_property
399
+ def neg_threshold(self) -> int:
400
+ return int(2 ** (self.value_bit_size - 1))
401
+
402
+ @cached_property
403
+ def neg_offset(self) -> int:
404
+ return int(2**self.value_bit_size)
405
+
406
+ def decoder_fn(self, data: bytes) -> int:
407
+ value = big_endian_to_int(data)
408
+ if value >= self.neg_threshold:
409
+ value -= self.neg_offset
410
+ return value
411
+
412
+ def validate_padding_bytes(self, value: Any, padding_bytes: bytes) -> None:
413
+ return validate_padding_bytes_signed_integer(self, value, padding_bytes)
414
+
415
+ @parse_type_str("int")
416
+ def from_type_str(cls, abi_type, registry):
417
+ return cls(value_bit_size=abi_type.sub)
418
+
419
+
420
+ class SignedIntegerDecoderCached(SignedIntegerDecoder):
421
+ decoder_fn: Callable[[bytes], int]
422
+ maxsize: Final[Optional[int]]
423
+
424
+ def __init__(self, maxsize: Optional[int] = None, **kwargs: Any) -> None:
425
+ super().__init__(**kwargs)
426
+ self.maxsize = maxsize
427
+ self.decoder_fn = lru_cache(maxsize=maxsize)(self.decoder_fn)
428
+
429
+
430
+ #
431
+ # Bytes1..32
432
+ #
433
+ class BytesDecoder(Fixed32ByteSizeDecoder[bytes]):
434
+ is_big_endian = False
435
+
436
+ @staticmethod
437
+ def decoder_fn(data: bytes) -> bytes:
438
+ return data
439
+
440
+ @parse_type_str("bytes")
441
+ def from_type_str(cls, abi_type, registry):
442
+ return cls(value_bit_size=abi_type.sub * 8)
443
+
444
+
445
+ class BaseFixedDecoder(Fixed32ByteSizeDecoder[decimal.Decimal]):
446
+ frac_places: int = None
447
+ is_big_endian = True
448
+
449
+ @cached_property
450
+ def denominator(self) -> decimal.Decimal:
451
+ return TEN**self.frac_places
452
+
453
+ def validate(self) -> None:
454
+ super().validate()
455
+
456
+ frac_places = self.frac_places
457
+ if frac_places is None:
458
+ raise ValueError("must specify `frac_places`")
459
+
460
+ if frac_places <= 0 or frac_places > 80:
461
+ raise ValueError("`frac_places` must be in range (0, 80)")
462
+
463
+
464
+ class UnsignedFixedDecoder(BaseFixedDecoder):
465
+ def decoder_fn(self, data: bytes) -> decimal.Decimal:
466
+ return decode_unsigned_fixed(self, data)
467
+
468
+ @parse_type_str("ufixed")
469
+ def from_type_str(cls, abi_type, registry):
470
+ value_bit_size, frac_places = abi_type.sub
471
+
472
+ return cls(value_bit_size=value_bit_size, frac_places=frac_places)
473
+
474
+
475
+ class SignedFixedDecoder(BaseFixedDecoder):
476
+ @cached_property
477
+ def neg_threshold(self) -> int:
478
+ return int(2 ** (self.value_bit_size - 1))
479
+
480
+ @cached_property
481
+ def neg_offset(self) -> int:
482
+ return int(2**self.value_bit_size)
483
+
484
+ @cached_property
485
+ def expected_padding_pos(self) -> bytes:
486
+ value_byte_size = get_value_byte_size(self)
487
+ padding_size = self.data_byte_size - value_byte_size
488
+ return b"\x00" * padding_size
489
+
490
+ @cached_property
491
+ def expected_padding_neg(self) -> bytes:
492
+ value_byte_size = get_value_byte_size(self)
493
+ padding_size = self.data_byte_size - value_byte_size
494
+ return b"\xff" * padding_size
495
+
496
+ def decoder_fn(self, data: bytes) -> decimal.Decimal:
497
+ return decode_signed_fixed(self, data)
498
+
499
+ def validate_padding_bytes(self, value: Any, padding_bytes: bytes) -> None:
500
+ if value >= 0:
501
+ expected_padding_bytes = self.expected_padding_pos
502
+ else:
503
+ expected_padding_bytes = self.expected_padding_neg
504
+
505
+ if padding_bytes != expected_padding_bytes:
506
+ raise NonEmptyPaddingBytes(
507
+ f"Padding bytes were not empty: {padding_bytes!r}"
508
+ )
509
+
510
+ @parse_type_str("fixed")
511
+ def from_type_str(cls, abi_type, registry):
512
+ value_bit_size, frac_places = abi_type.sub
513
+
514
+ return cls(value_bit_size=value_bit_size, frac_places=frac_places)
515
+
516
+
517
+ #
518
+ # String and Bytes
519
+ #
520
+ class ByteStringDecoder(SingleDecoder[TByteStr]):
521
+ is_dynamic = True
522
+
523
+ @staticmethod
524
+ def decoder_fn(data: bytes) -> bytes:
525
+ return data
526
+
527
+ @final
528
+ def read_data_from_stream(self, stream: ContextFramesBytesIO) -> bytes:
529
+ return read_bytestring_from_stream(self, stream)
530
+
531
+ def validate_padding_bytes(self, value: Any, padding_bytes: bytes) -> None:
532
+ pass
533
+
534
+ @parse_type_str("bytes")
535
+ def from_type_str(cls, abi_type, registry):
536
+ return cls()
537
+
538
+
539
+ class StringDecoder(ByteStringDecoder[str]):
540
+ def __init__(self, handle_string_errors: str = "strict") -> None:
541
+ self.bytes_errors: Final = handle_string_errors
542
+ super().__init__()
543
+
544
+ @parse_type_str("string")
545
+ def from_type_str(cls, abi_type, registry):
546
+ return cls()
547
+
548
+ def decode(self, stream: ContextFramesBytesIO) -> str:
549
+ return decode_string(self, stream)
550
+
551
+ __call__ = decode
552
+
553
+ @staticmethod
554
+ def decoder_fn(data: bytes, handle_string_errors: str = "strict") -> str:
555
+ return data.decode("utf-8", errors=handle_string_errors)