faster-eth-abi 5.2.5__cp313-cp313-macosx_11_0_arm64.whl → 5.2.20__cp313-cp313-macosx_11_0_arm64.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.
Potentially problematic release.
This version of faster-eth-abi might be problematic. Click here for more details.
- faster_eth_abi/_codec.cpython-313-darwin.so +0 -0
- faster_eth_abi/_codec.py +8 -7
- faster_eth_abi/_decoding.cpython-313-darwin.so +0 -0
- faster_eth_abi/_decoding.py +299 -0
- faster_eth_abi/_encoding.cpython-313-darwin.so +0 -0
- faster_eth_abi/_encoding.py +163 -14
- faster_eth_abi/_grammar.cpython-313-darwin.so +0 -0
- faster_eth_abi/_grammar.py +375 -0
- faster_eth_abi/abi.cpython-313-darwin.so +0 -0
- faster_eth_abi/base.py +5 -1
- faster_eth_abi/codec.py +2675 -9
- faster_eth_abi/constants.cpython-313-darwin.so +0 -0
- faster_eth_abi/decoding.py +263 -242
- faster_eth_abi/encoding.py +175 -71
- faster_eth_abi/exceptions.py +26 -14
- faster_eth_abi/from_type_str.cpython-313-darwin.so +0 -0
- faster_eth_abi/from_type_str.py +7 -1
- faster_eth_abi/grammar.py +30 -325
- faster_eth_abi/io.py +5 -1
- faster_eth_abi/packed.cpython-313-darwin.so +0 -0
- faster_eth_abi/packed.py +4 -0
- faster_eth_abi/registry.py +186 -91
- faster_eth_abi/tools/__init__.cpython-313-darwin.so +0 -0
- faster_eth_abi/tools/_strategies.cpython-313-darwin.so +0 -0
- faster_eth_abi/tools/_strategies.py +12 -6
- faster_eth_abi/typing.py +4627 -0
- faster_eth_abi/utils/__init__.cpython-313-darwin.so +0 -0
- faster_eth_abi/utils/numeric.cpython-313-darwin.so +0 -0
- faster_eth_abi/utils/numeric.py +51 -20
- faster_eth_abi/utils/padding.cpython-313-darwin.so +0 -0
- faster_eth_abi/utils/string.cpython-313-darwin.so +0 -0
- faster_eth_abi/utils/validation.cpython-313-darwin.so +0 -0
- {faster_eth_abi-5.2.5.dist-info → faster_eth_abi-5.2.20.dist-info}/METADATA +52 -11
- faster_eth_abi-5.2.20.dist-info/RECORD +46 -0
- faster_eth_abi-5.2.20.dist-info/top_level.txt +2 -0
- faster_eth_abi__mypyc.cpython-313-darwin.so +0 -0
- c42f5c78bc058f310136__mypyc.cpython-313-darwin.so +0 -0
- faster_eth_abi-5.2.5.dist-info/RECORD +0 -42
- faster_eth_abi-5.2.5.dist-info/licenses/LICENSE +0 -21
- faster_eth_abi-5.2.5.dist-info/top_level.txt +0 -3
- {faster_eth_abi-5.2.5.dist-info → faster_eth_abi-5.2.20.dist-info}/WHEEL +0 -0
faster_eth_abi/encoding.py
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
|
+
"""Classes for ABI encoding logic.
|
|
2
|
+
|
|
3
|
+
Implements classes and functions for serializing Python values into binary data
|
|
4
|
+
according to ABI type specifications.
|
|
5
|
+
"""
|
|
1
6
|
import abc
|
|
2
7
|
import codecs
|
|
3
8
|
import decimal
|
|
9
|
+
from functools import (
|
|
10
|
+
cached_property,
|
|
11
|
+
lru_cache,
|
|
12
|
+
)
|
|
13
|
+
from types import (
|
|
14
|
+
MethodType,
|
|
15
|
+
)
|
|
4
16
|
from typing import (
|
|
5
17
|
Any,
|
|
18
|
+
Callable,
|
|
19
|
+
ClassVar,
|
|
20
|
+
Final,
|
|
6
21
|
NoReturn,
|
|
7
22
|
Optional,
|
|
8
23
|
Sequence,
|
|
9
24
|
Tuple,
|
|
10
25
|
Type,
|
|
26
|
+
final,
|
|
11
27
|
)
|
|
12
28
|
|
|
13
29
|
from faster_eth_utils import (
|
|
@@ -20,6 +36,9 @@ from faster_eth_utils import (
|
|
|
20
36
|
is_text,
|
|
21
37
|
to_canonical_address,
|
|
22
38
|
)
|
|
39
|
+
from typing_extensions import (
|
|
40
|
+
Self,
|
|
41
|
+
)
|
|
23
42
|
|
|
24
43
|
from faster_eth_abi._encoding import (
|
|
25
44
|
encode_elements,
|
|
@@ -27,7 +46,11 @@ from faster_eth_abi._encoding import (
|
|
|
27
46
|
encode_fixed,
|
|
28
47
|
encode_signed,
|
|
29
48
|
encode_tuple,
|
|
49
|
+
encode_tuple_all_dynamic,
|
|
50
|
+
encode_tuple_no_dynamic,
|
|
51
|
+
encode_tuple_no_dynamic_funcs,
|
|
30
52
|
int_to_big_endian,
|
|
53
|
+
validate_tuple,
|
|
31
54
|
)
|
|
32
55
|
from faster_eth_abi.base import (
|
|
33
56
|
BaseCoder,
|
|
@@ -73,7 +96,7 @@ class BaseEncoder(BaseCoder, metaclass=abc.ABCMeta):
|
|
|
73
96
|
"""
|
|
74
97
|
|
|
75
98
|
@abc.abstractmethod
|
|
76
|
-
def validate_value(self, value: Any) -> None:
|
|
99
|
+
def validate_value(self, value: Any) -> None:
|
|
77
100
|
"""
|
|
78
101
|
Checks whether or not the given value can be encoded by this encoder.
|
|
79
102
|
If the given value cannot be encoded, must raise
|
|
@@ -106,38 +129,51 @@ class TupleEncoder(BaseEncoder):
|
|
|
106
129
|
def __init__(self, encoders: Tuple[BaseEncoder, ...], **kwargs: Any) -> None:
|
|
107
130
|
super().__init__(encoders=encoders, **kwargs)
|
|
108
131
|
|
|
109
|
-
self.
|
|
132
|
+
self._is_dynamic: Final = tuple(
|
|
133
|
+
getattr(e, "is_dynamic", False) for e in self.encoders
|
|
134
|
+
)
|
|
135
|
+
self.is_dynamic = any(self._is_dynamic)
|
|
136
|
+
|
|
137
|
+
validators = []
|
|
138
|
+
for encoder in self.encoders:
|
|
139
|
+
try:
|
|
140
|
+
validator = encoder.validate_value
|
|
141
|
+
except AttributeError:
|
|
142
|
+
validators.append(encoder)
|
|
143
|
+
else:
|
|
144
|
+
validators.append(validator)
|
|
145
|
+
|
|
146
|
+
self.validators: Final[Callable[[Any], None]] = tuple(validators)
|
|
147
|
+
|
|
148
|
+
if type(self).encode is TupleEncoder.encode:
|
|
149
|
+
encode_func = (
|
|
150
|
+
encode_tuple_all_dynamic
|
|
151
|
+
if all(self._is_dynamic)
|
|
152
|
+
else encode_tuple_no_dynamic_funcs.get(
|
|
153
|
+
len(self.encoders),
|
|
154
|
+
encode_tuple_no_dynamic,
|
|
155
|
+
)
|
|
156
|
+
if not self.is_dynamic
|
|
157
|
+
else encode_tuple
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
self.encode = MethodType(encode_func, self)
|
|
110
161
|
|
|
111
|
-
def validate(self):
|
|
162
|
+
def validate(self) -> None:
|
|
112
163
|
super().validate()
|
|
113
164
|
|
|
114
165
|
if self.encoders is None:
|
|
115
166
|
raise ValueError("`encoders` may not be none")
|
|
116
167
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
value,
|
|
121
|
-
msg="must be list-like object such as array or tuple",
|
|
122
|
-
)
|
|
168
|
+
@final
|
|
169
|
+
def validate_value(self, value: Sequence[Any]) -> None:
|
|
170
|
+
validate_tuple(self, value)
|
|
123
171
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
value,
|
|
127
|
-
exc=ValueOutOfBounds,
|
|
128
|
-
msg=f"value has {len(value)} items when {len(self.encoders)} "
|
|
129
|
-
"were expected",
|
|
130
|
-
)
|
|
172
|
+
def encode(self, values: Sequence[Any]) -> bytes:
|
|
173
|
+
return encode_tuple(self, values)
|
|
131
174
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
encoder.validate_value(item)
|
|
135
|
-
except AttributeError:
|
|
136
|
-
encoder(item)
|
|
137
|
-
|
|
138
|
-
def encode(self, values):
|
|
139
|
-
self.validate_value(values)
|
|
140
|
-
return encode_tuple(values, self.encoders)
|
|
175
|
+
def __call__(self, values: Sequence[Any]) -> bytes:
|
|
176
|
+
return self.encode(values)
|
|
141
177
|
|
|
142
178
|
@parse_tuple_type_str
|
|
143
179
|
def from_type_str(cls, abi_type, registry):
|
|
@@ -155,37 +191,39 @@ class FixedSizeEncoder(BaseEncoder):
|
|
|
155
191
|
type_check_fn = None
|
|
156
192
|
is_big_endian = None
|
|
157
193
|
|
|
158
|
-
def validate(self):
|
|
194
|
+
def validate(self) -> None:
|
|
159
195
|
super().validate()
|
|
160
196
|
|
|
161
|
-
|
|
197
|
+
value_bit_size = self.value_bit_size
|
|
198
|
+
if value_bit_size is None:
|
|
162
199
|
raise ValueError("`value_bit_size` may not be none")
|
|
163
|
-
|
|
200
|
+
data_byte_size = self.data_byte_size
|
|
201
|
+
if data_byte_size is None:
|
|
164
202
|
raise ValueError("`data_byte_size` may not be none")
|
|
165
203
|
if self.encode_fn is None:
|
|
166
204
|
raise ValueError("`encode_fn` may not be none")
|
|
167
205
|
if self.is_big_endian is None:
|
|
168
206
|
raise ValueError("`is_big_endian` may not be none")
|
|
169
207
|
|
|
170
|
-
if
|
|
208
|
+
if value_bit_size % 8 != 0:
|
|
171
209
|
raise ValueError(
|
|
172
|
-
f"Invalid value bit size: {
|
|
173
|
-
"Must be a multiple of 8"
|
|
210
|
+
f"Invalid value bit size: {value_bit_size}. Must be a multiple of 8"
|
|
174
211
|
)
|
|
175
212
|
|
|
176
|
-
if
|
|
213
|
+
if value_bit_size > data_byte_size * 8:
|
|
177
214
|
raise ValueError("Value byte size exceeds data size")
|
|
178
215
|
|
|
179
|
-
def validate_value(self, value):
|
|
216
|
+
def validate_value(self, value: Any) -> None:
|
|
180
217
|
raise NotImplementedError("Must be implemented by subclasses")
|
|
181
218
|
|
|
182
219
|
def encode(self, value: Any) -> bytes:
|
|
183
220
|
self.validate_value(value)
|
|
184
|
-
|
|
221
|
+
encode_fn = self.encode_fn
|
|
222
|
+
if encode_fn is None:
|
|
185
223
|
raise AssertionError("`encode_fn` is None")
|
|
186
|
-
return encode_fixed(
|
|
187
|
-
|
|
188
|
-
|
|
224
|
+
return encode_fixed(value, encode_fn, self.is_big_endian, self.data_byte_size)
|
|
225
|
+
|
|
226
|
+
__call__ = encode
|
|
189
227
|
|
|
190
228
|
|
|
191
229
|
class Fixed32ByteSizeEncoder(FixedSizeEncoder):
|
|
@@ -202,7 +240,7 @@ class BooleanEncoder(Fixed32ByteSizeEncoder):
|
|
|
202
240
|
cls.invalidate_value(value)
|
|
203
241
|
|
|
204
242
|
@classmethod
|
|
205
|
-
def encode_fn(cls, value):
|
|
243
|
+
def encode_fn(cls, value: bool) -> bytes:
|
|
206
244
|
if value is True:
|
|
207
245
|
return b"\x01"
|
|
208
246
|
elif value is False:
|
|
@@ -225,7 +263,7 @@ class NumberEncoder(Fixed32ByteSizeEncoder):
|
|
|
225
263
|
illegal_value_fn = None
|
|
226
264
|
type_check_fn = None
|
|
227
265
|
|
|
228
|
-
def validate(self):
|
|
266
|
+
def validate(self) -> None:
|
|
229
267
|
super().validate()
|
|
230
268
|
|
|
231
269
|
if self.bounds_fn is None:
|
|
@@ -233,15 +271,15 @@ class NumberEncoder(Fixed32ByteSizeEncoder):
|
|
|
233
271
|
if self.type_check_fn is None:
|
|
234
272
|
raise ValueError("`type_check_fn` cannot be null")
|
|
235
273
|
|
|
236
|
-
def validate_value(self, value):
|
|
237
|
-
|
|
274
|
+
def validate_value(self, value: Any) -> None:
|
|
275
|
+
type_check_fn = self.type_check_fn
|
|
276
|
+
if type_check_fn is None:
|
|
238
277
|
raise AssertionError("`type_check_fn` is None")
|
|
239
|
-
if not
|
|
278
|
+
if not type_check_fn(value):
|
|
240
279
|
self.invalidate_value(value)
|
|
241
280
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
)
|
|
281
|
+
illegal_value_fn = self.illegal_value_fn
|
|
282
|
+
illegal_value = illegal_value_fn is not None and illegal_value_fn(value)
|
|
245
283
|
if illegal_value:
|
|
246
284
|
self.invalidate_value(value, exc=IllegalValue)
|
|
247
285
|
|
|
@@ -265,6 +303,16 @@ class UnsignedIntegerEncoder(NumberEncoder):
|
|
|
265
303
|
return cls(value_bit_size=abi_type.sub)
|
|
266
304
|
|
|
267
305
|
|
|
306
|
+
class UnsignedIntegerEncoderCached(UnsignedIntegerEncoder):
|
|
307
|
+
encode: Final[Callable[[int], bytes]]
|
|
308
|
+
maxsize: Final[Optional[int]]
|
|
309
|
+
|
|
310
|
+
def __init__(self, maxsize: Optional[int] = None, **kwargs: Any) -> None:
|
|
311
|
+
super().__init__(**kwargs)
|
|
312
|
+
self.maxsize = maxsize
|
|
313
|
+
self.encode = lru_cache(maxsize=maxsize)(self.encode)
|
|
314
|
+
|
|
315
|
+
|
|
268
316
|
encode_uint_256 = UnsignedIntegerEncoder(value_bit_size=256, data_byte_size=32)
|
|
269
317
|
|
|
270
318
|
|
|
@@ -277,6 +325,16 @@ class PackedUnsignedIntegerEncoder(UnsignedIntegerEncoder):
|
|
|
277
325
|
)
|
|
278
326
|
|
|
279
327
|
|
|
328
|
+
class PackedUnsignedIntegerEncoderCached(PackedUnsignedIntegerEncoder):
|
|
329
|
+
encode: Final[Callable[[int], bytes]]
|
|
330
|
+
maxsize: Final[Optional[int]]
|
|
331
|
+
|
|
332
|
+
def __init__(self, maxsize: Optional[int] = None, **kwargs: Any) -> None:
|
|
333
|
+
super().__init__(**kwargs)
|
|
334
|
+
self.maxsize = maxsize
|
|
335
|
+
self.encode = lru_cache(maxsize=maxsize)(self.encode)
|
|
336
|
+
|
|
337
|
+
|
|
280
338
|
class SignedIntegerEncoder(NumberEncoder):
|
|
281
339
|
bounds_fn = staticmethod(compute_signed_integer_bounds)
|
|
282
340
|
type_check_fn = staticmethod(is_integer)
|
|
@@ -284,15 +342,27 @@ class SignedIntegerEncoder(NumberEncoder):
|
|
|
284
342
|
def encode_fn(self, value: int) -> bytes:
|
|
285
343
|
return int_to_big_endian(value % (2**self.value_bit_size))
|
|
286
344
|
|
|
287
|
-
def encode(self, value):
|
|
345
|
+
def encode(self, value: int) -> bytes:
|
|
288
346
|
self.validate_value(value)
|
|
289
347
|
return encode_signed(value, self.encode_fn, self.data_byte_size)
|
|
290
348
|
|
|
349
|
+
__call__ = encode
|
|
350
|
+
|
|
291
351
|
@parse_type_str("int")
|
|
292
352
|
def from_type_str(cls, abi_type, registry):
|
|
293
353
|
return cls(value_bit_size=abi_type.sub)
|
|
294
354
|
|
|
295
355
|
|
|
356
|
+
class SignedIntegerEncoderCached(SignedIntegerEncoder):
|
|
357
|
+
encode: Final[Callable[[int], bytes]]
|
|
358
|
+
maxsize: Final[Optional[int]]
|
|
359
|
+
|
|
360
|
+
def __init__(self, maxsize: Optional[int] = None, **kwargs: Any) -> None:
|
|
361
|
+
super().__init__(**kwargs)
|
|
362
|
+
self.maxsize = maxsize
|
|
363
|
+
self.encode = lru_cache(maxsize=maxsize)(self.encode)
|
|
364
|
+
|
|
365
|
+
|
|
296
366
|
class PackedSignedIntegerEncoder(SignedIntegerEncoder):
|
|
297
367
|
@parse_type_str("int")
|
|
298
368
|
def from_type_str(cls, abi_type, registry):
|
|
@@ -302,6 +372,16 @@ class PackedSignedIntegerEncoder(SignedIntegerEncoder):
|
|
|
302
372
|
)
|
|
303
373
|
|
|
304
374
|
|
|
375
|
+
class PackedSignedIntegerEncoderCached(PackedSignedIntegerEncoder):
|
|
376
|
+
encode: Final[Callable[[int], bytes]]
|
|
377
|
+
maxsize: Final[Optional[int]]
|
|
378
|
+
|
|
379
|
+
def __init__(self, maxsize: Optional[int] = None, **kwargs: Any) -> None:
|
|
380
|
+
super().__init__(**kwargs)
|
|
381
|
+
self.maxsize = maxsize
|
|
382
|
+
self.encode = lru_cache(maxsize=maxsize)(self.encode)
|
|
383
|
+
|
|
384
|
+
|
|
305
385
|
class BaseFixedEncoder(NumberEncoder):
|
|
306
386
|
frac_places = None
|
|
307
387
|
|
|
@@ -316,11 +396,19 @@ class BaseFixedEncoder(NumberEncoder):
|
|
|
316
396
|
|
|
317
397
|
return False
|
|
318
398
|
|
|
399
|
+
@cached_property
|
|
400
|
+
def denominator(self) -> decimal.Decimal:
|
|
401
|
+
return TEN**self.frac_places
|
|
402
|
+
|
|
403
|
+
@cached_property
|
|
404
|
+
def precision(self) -> int:
|
|
405
|
+
return TEN**-self.frac_places
|
|
406
|
+
|
|
319
407
|
def validate_value(self, value):
|
|
320
408
|
super().validate_value(value)
|
|
321
409
|
|
|
322
410
|
with decimal.localcontext(abi_decimal_context):
|
|
323
|
-
residue = value %
|
|
411
|
+
residue = value % self.precision
|
|
324
412
|
|
|
325
413
|
if residue > 0:
|
|
326
414
|
self.invalidate_value(
|
|
@@ -330,13 +418,14 @@ class BaseFixedEncoder(NumberEncoder):
|
|
|
330
418
|
f"{self.frac_places}",
|
|
331
419
|
)
|
|
332
420
|
|
|
333
|
-
def validate(self):
|
|
421
|
+
def validate(self) -> None:
|
|
334
422
|
super().validate()
|
|
335
423
|
|
|
336
|
-
|
|
424
|
+
frac_places = self.frac_places
|
|
425
|
+
if frac_places is None:
|
|
337
426
|
raise ValueError("must specify `frac_places`")
|
|
338
427
|
|
|
339
|
-
if
|
|
428
|
+
if frac_places <= 0 or frac_places > 80:
|
|
340
429
|
raise ValueError("`frac_places` must be in range (0, 80]")
|
|
341
430
|
|
|
342
431
|
|
|
@@ -344,9 +433,9 @@ class UnsignedFixedEncoder(BaseFixedEncoder):
|
|
|
344
433
|
def bounds_fn(self, value_bit_size):
|
|
345
434
|
return compute_unsigned_fixed_bounds(self.value_bit_size, self.frac_places)
|
|
346
435
|
|
|
347
|
-
def encode_fn(self, value):
|
|
436
|
+
def encode_fn(self, value: decimal.Decimal) -> bytes:
|
|
348
437
|
with decimal.localcontext(abi_decimal_context):
|
|
349
|
-
scaled_value = value *
|
|
438
|
+
scaled_value = value * self.denominator
|
|
350
439
|
integer_value = int(scaled_value)
|
|
351
440
|
|
|
352
441
|
return int_to_big_endian(integer_value)
|
|
@@ -377,19 +466,21 @@ class SignedFixedEncoder(BaseFixedEncoder):
|
|
|
377
466
|
def bounds_fn(self, value_bit_size):
|
|
378
467
|
return compute_signed_fixed_bounds(self.value_bit_size, self.frac_places)
|
|
379
468
|
|
|
380
|
-
def encode_fn(self, value):
|
|
469
|
+
def encode_fn(self, value: decimal.Decimal) -> bytes:
|
|
381
470
|
with decimal.localcontext(abi_decimal_context):
|
|
382
|
-
scaled_value = value *
|
|
471
|
+
scaled_value = value * self.denominator
|
|
383
472
|
integer_value = int(scaled_value)
|
|
384
473
|
|
|
385
474
|
unsigned_integer_value = integer_value % (2**self.value_bit_size)
|
|
386
475
|
|
|
387
476
|
return int_to_big_endian(unsigned_integer_value)
|
|
388
477
|
|
|
389
|
-
def encode(self, value):
|
|
478
|
+
def encode(self, value: decimal.Decimal) -> bytes:
|
|
390
479
|
self.validate_value(value)
|
|
391
480
|
return encode_signed(value, self.encode_fn, self.data_byte_size)
|
|
392
481
|
|
|
482
|
+
__call__ = encode
|
|
483
|
+
|
|
393
484
|
@parse_type_str("fixed")
|
|
394
485
|
def from_type_str(cls, abi_type, registry):
|
|
395
486
|
value_bit_size, frac_places = abi_type.sub
|
|
@@ -422,7 +513,7 @@ class AddressEncoder(Fixed32ByteSizeEncoder):
|
|
|
422
513
|
if not is_address(value):
|
|
423
514
|
cls.invalidate_value(value)
|
|
424
515
|
|
|
425
|
-
def validate(self):
|
|
516
|
+
def validate(self) -> None:
|
|
426
517
|
super().validate()
|
|
427
518
|
|
|
428
519
|
if self.value_bit_size != 20 * 8:
|
|
@@ -453,7 +544,7 @@ class BytesEncoder(Fixed32ByteSizeEncoder):
|
|
|
453
544
|
)
|
|
454
545
|
|
|
455
546
|
@staticmethod
|
|
456
|
-
def encode_fn(value):
|
|
547
|
+
def encode_fn(value: bytes) -> bytes:
|
|
457
548
|
return value
|
|
458
549
|
|
|
459
550
|
@parse_type_str("bytes")
|
|
@@ -479,7 +570,7 @@ class ByteStringEncoder(BaseEncoder):
|
|
|
479
570
|
cls.invalidate_value(value)
|
|
480
571
|
|
|
481
572
|
@classmethod
|
|
482
|
-
def encode(cls, value):
|
|
573
|
+
def encode(cls, value: bytes) -> bytes:
|
|
483
574
|
cls.validate_value(value)
|
|
484
575
|
value_length = len(value)
|
|
485
576
|
|
|
@@ -488,19 +579,23 @@ class ByteStringEncoder(BaseEncoder):
|
|
|
488
579
|
|
|
489
580
|
return encoded_size + padded_value
|
|
490
581
|
|
|
582
|
+
__call__: ClassVar[Callable[[Type[Self], bytes], bytes]] = encode
|
|
583
|
+
|
|
491
584
|
@parse_type_str("bytes")
|
|
492
585
|
def from_type_str(cls, abi_type, registry):
|
|
493
|
-
return cls()
|
|
586
|
+
return cls() # type: ignore [misc]
|
|
494
587
|
|
|
495
588
|
|
|
496
589
|
class PackedByteStringEncoder(ByteStringEncoder):
|
|
497
590
|
is_dynamic = False
|
|
498
591
|
|
|
499
592
|
@classmethod
|
|
500
|
-
def encode(cls, value):
|
|
593
|
+
def encode(cls, value: bytes) -> bytes:
|
|
501
594
|
cls.validate_value(value)
|
|
502
595
|
return value
|
|
503
596
|
|
|
597
|
+
__call__ = encode
|
|
598
|
+
|
|
504
599
|
|
|
505
600
|
class TextStringEncoder(BaseEncoder):
|
|
506
601
|
is_dynamic = True
|
|
@@ -511,7 +606,7 @@ class TextStringEncoder(BaseEncoder):
|
|
|
511
606
|
cls.invalidate_value(value)
|
|
512
607
|
|
|
513
608
|
@classmethod
|
|
514
|
-
def encode(cls, value):
|
|
609
|
+
def encode(cls, value: str) -> bytes:
|
|
515
610
|
cls.validate_value(value)
|
|
516
611
|
|
|
517
612
|
value_as_bytes = codecs.encode(value, "utf8")
|
|
@@ -522,24 +617,28 @@ class TextStringEncoder(BaseEncoder):
|
|
|
522
617
|
|
|
523
618
|
return encoded_size + padded_value
|
|
524
619
|
|
|
620
|
+
__call__: ClassVar[Callable[[Type[Self], str], bytes]] = encode
|
|
621
|
+
|
|
525
622
|
@parse_type_str("string")
|
|
526
623
|
def from_type_str(cls, abi_type, registry):
|
|
527
|
-
return cls()
|
|
624
|
+
return cls() # type: ignore [misc]
|
|
528
625
|
|
|
529
626
|
|
|
530
627
|
class PackedTextStringEncoder(TextStringEncoder):
|
|
531
628
|
is_dynamic = False
|
|
532
629
|
|
|
533
630
|
@classmethod
|
|
534
|
-
def encode(cls, value):
|
|
631
|
+
def encode(cls, value: str) -> bytes:
|
|
535
632
|
cls.validate_value(value)
|
|
536
633
|
return codecs.encode(value, "utf8")
|
|
537
634
|
|
|
635
|
+
__call__ = encode
|
|
636
|
+
|
|
538
637
|
|
|
539
638
|
class BaseArrayEncoder(BaseEncoder):
|
|
540
|
-
item_encoder = None
|
|
639
|
+
item_encoder: BaseEncoder = None
|
|
541
640
|
|
|
542
|
-
def validate(self):
|
|
641
|
+
def validate(self) -> None:
|
|
543
642
|
super().validate()
|
|
544
643
|
|
|
545
644
|
if self.item_encoder is None:
|
|
@@ -552,8 +651,9 @@ class BaseArrayEncoder(BaseEncoder):
|
|
|
552
651
|
msg="must be list-like such as array or tuple",
|
|
553
652
|
)
|
|
554
653
|
|
|
654
|
+
item_encoder = self.item_encoder
|
|
555
655
|
for item in value:
|
|
556
|
-
|
|
656
|
+
item_encoder.validate_value(item)
|
|
557
657
|
|
|
558
658
|
def encode_elements(self, value: Sequence[Any]) -> bytes:
|
|
559
659
|
self.validate_value(value)
|
|
@@ -581,17 +681,19 @@ class PackedArrayEncoder(BaseArrayEncoder):
|
|
|
581
681
|
def validate_value(self, value: Any) -> None:
|
|
582
682
|
super().validate_value(value)
|
|
583
683
|
|
|
584
|
-
|
|
684
|
+
array_size = self.array_size
|
|
685
|
+
if array_size is not None and len(value) != array_size:
|
|
585
686
|
self.invalidate_value(
|
|
586
687
|
value,
|
|
587
688
|
exc=ValueOutOfBounds,
|
|
588
|
-
msg=f"value has {len(value)} items when {
|
|
589
|
-
"expected",
|
|
689
|
+
msg=f"value has {len(value)} items when {array_size} were expected",
|
|
590
690
|
)
|
|
591
691
|
|
|
592
692
|
def encode(self, value: Sequence[Any]) -> bytes:
|
|
593
693
|
return encode_elements(self.item_encoder, value)
|
|
594
694
|
|
|
695
|
+
__call__ = encode
|
|
696
|
+
|
|
595
697
|
@parse_type_str(with_arrlist=True)
|
|
596
698
|
def from_type_str(cls, abi_type, registry):
|
|
597
699
|
item_encoder = registry.get_encoder(abi_type.item_type.to_type_str())
|
|
@@ -609,12 +711,12 @@ class PackedArrayEncoder(BaseArrayEncoder):
|
|
|
609
711
|
class SizedArrayEncoder(BaseArrayEncoder):
|
|
610
712
|
array_size = None
|
|
611
713
|
|
|
612
|
-
def __init__(self, **kwargs):
|
|
714
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
613
715
|
super().__init__(**kwargs)
|
|
614
716
|
|
|
615
717
|
self.is_dynamic = self.item_encoder.is_dynamic
|
|
616
718
|
|
|
617
|
-
def validate(self):
|
|
719
|
+
def validate(self) -> None:
|
|
618
720
|
super().validate()
|
|
619
721
|
|
|
620
722
|
if self.array_size is None:
|
|
@@ -634,6 +736,8 @@ class SizedArrayEncoder(BaseArrayEncoder):
|
|
|
634
736
|
def encode(self, value: Sequence[Any]) -> bytes:
|
|
635
737
|
return encode_elements(self.item_encoder, value)
|
|
636
738
|
|
|
739
|
+
__call__ = encode
|
|
740
|
+
|
|
637
741
|
|
|
638
742
|
class DynamicArrayEncoder(BaseArrayEncoder):
|
|
639
743
|
is_dynamic = True
|
faster_eth_abi/exceptions.py
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
# mypy: disable-error-code="misc"
|
|
2
|
+
# cannot subclass `Any`
|
|
2
3
|
|
|
4
|
+
"""
|
|
5
|
+
Exception classes for error handling during ABI encoding and decoding operations.
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
faster-eth-abi exceptions always inherit from eth-abi exceptions, so porting to faster-eth-abi
|
|
8
|
+
does not require any change to your existing exception handlers. They will continue to work.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import eth_abi.exceptions
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EncodingError(eth_abi.exceptions.EncodingError):
|
|
5
15
|
"""
|
|
6
16
|
Base exception for any error that occurs during encoding.
|
|
7
17
|
"""
|
|
8
18
|
|
|
9
19
|
|
|
10
|
-
class EncodingTypeError(EncodingError):
|
|
20
|
+
class EncodingTypeError(EncodingError, eth_abi.exceptions.EncodingTypeError):
|
|
11
21
|
"""
|
|
12
22
|
Raised when trying to encode a python value whose type is not supported for
|
|
13
23
|
the output ABI type.
|
|
14
24
|
"""
|
|
15
25
|
|
|
16
26
|
|
|
17
|
-
class IllegalValue(EncodingError):
|
|
27
|
+
class IllegalValue(EncodingError, eth_abi.exceptions.IllegalValue):
|
|
18
28
|
"""
|
|
19
29
|
Raised when trying to encode a python value with the correct type but with
|
|
20
30
|
a value that is not considered legal for the output ABI type.
|
|
@@ -26,7 +36,7 @@ class IllegalValue(EncodingError):
|
|
|
26
36
|
"""
|
|
27
37
|
|
|
28
38
|
|
|
29
|
-
class ValueOutOfBounds(IllegalValue):
|
|
39
|
+
class ValueOutOfBounds(IllegalValue, eth_abi.exceptions.ValueOutOfBounds):
|
|
30
40
|
"""
|
|
31
41
|
Raised when trying to encode a python value with the correct type but with
|
|
32
42
|
a value that appears outside the range of valid values for the output ABI
|
|
@@ -39,31 +49,31 @@ class ValueOutOfBounds(IllegalValue):
|
|
|
39
49
|
"""
|
|
40
50
|
|
|
41
51
|
|
|
42
|
-
class DecodingError(
|
|
52
|
+
class DecodingError(eth_abi.exceptions.DecodingError):
|
|
43
53
|
"""
|
|
44
54
|
Base exception for any error that occurs during decoding.
|
|
45
55
|
"""
|
|
46
56
|
|
|
47
57
|
|
|
48
|
-
class InsufficientDataBytes(DecodingError):
|
|
58
|
+
class InsufficientDataBytes(DecodingError, eth_abi.exceptions.InsufficientDataBytes):
|
|
49
59
|
"""
|
|
50
60
|
Raised when there are insufficient data to decode a value for a given ABI type.
|
|
51
61
|
"""
|
|
52
62
|
|
|
53
63
|
|
|
54
|
-
class NonEmptyPaddingBytes(DecodingError):
|
|
64
|
+
class NonEmptyPaddingBytes(DecodingError, eth_abi.exceptions.NonEmptyPaddingBytes):
|
|
55
65
|
"""
|
|
56
66
|
Raised when the padding bytes of an ABI value are malformed.
|
|
57
67
|
"""
|
|
58
68
|
|
|
59
69
|
|
|
60
|
-
class InvalidPointer(DecodingError):
|
|
70
|
+
class InvalidPointer(DecodingError, eth_abi.exceptions.InvalidPointer):
|
|
61
71
|
"""
|
|
62
72
|
Raised when the pointer to a value in the ABI encoding is invalid.
|
|
63
73
|
"""
|
|
64
74
|
|
|
65
75
|
|
|
66
|
-
class ParseError(
|
|
76
|
+
class ParseError(eth_abi.exceptions.ParseError):
|
|
67
77
|
"""
|
|
68
78
|
Raised when an ABI type string cannot be parsed.
|
|
69
79
|
"""
|
|
@@ -75,7 +85,7 @@ class ParseError(parsimonious.ParseError): # type: ignore[misc] # subclasses An
|
|
|
75
85
|
)
|
|
76
86
|
|
|
77
87
|
|
|
78
|
-
class ABITypeError(
|
|
88
|
+
class ABITypeError(eth_abi.exceptions.ABITypeError):
|
|
79
89
|
"""
|
|
80
90
|
Raised when a parsed ABI type has inconsistent properties; for example,
|
|
81
91
|
when trying to parse the type string ``'uint7'`` (which has a bit-width
|
|
@@ -83,13 +93,13 @@ class ABITypeError(ValueError):
|
|
|
83
93
|
"""
|
|
84
94
|
|
|
85
95
|
|
|
86
|
-
class PredicateMappingError(
|
|
96
|
+
class PredicateMappingError(eth_abi.exceptions.PredicateMappingError):
|
|
87
97
|
"""
|
|
88
98
|
Raised when an error occurs in a registry's internal mapping.
|
|
89
99
|
"""
|
|
90
100
|
|
|
91
101
|
|
|
92
|
-
class NoEntriesFound(
|
|
102
|
+
class NoEntriesFound(PredicateMappingError, eth_abi.exceptions.NoEntriesFound):
|
|
93
103
|
"""
|
|
94
104
|
Raised when no registration is found for a type string in a registry's
|
|
95
105
|
internal mapping.
|
|
@@ -101,7 +111,9 @@ class NoEntriesFound(ValueError, PredicateMappingError):
|
|
|
101
111
|
"""
|
|
102
112
|
|
|
103
113
|
|
|
104
|
-
class MultipleEntriesFound(
|
|
114
|
+
class MultipleEntriesFound(
|
|
115
|
+
PredicateMappingError, eth_abi.exceptions.MultipleEntriesFound
|
|
116
|
+
):
|
|
105
117
|
"""
|
|
106
118
|
Raised when multiple registrations are found for a type string in a
|
|
107
119
|
registry's internal mapping. This error is non-recoverable and indicates
|
|
Binary file
|
faster_eth_abi/from_type_str.py
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
"""Helpers for parsing and normalizing ABI type strings.
|
|
2
|
+
|
|
3
|
+
Provides decorators and utilities for implementing from_type_str methods on coder classes.
|
|
4
|
+
"""
|
|
1
5
|
import functools
|
|
2
6
|
from typing import (
|
|
3
7
|
TYPE_CHECKING,
|
|
@@ -12,11 +16,13 @@ from eth_typing import (
|
|
|
12
16
|
TypeStr,
|
|
13
17
|
)
|
|
14
18
|
|
|
15
|
-
from .
|
|
19
|
+
from ._grammar import (
|
|
16
20
|
ABIType,
|
|
17
21
|
BasicType,
|
|
18
22
|
TupleType,
|
|
19
23
|
normalize,
|
|
24
|
+
)
|
|
25
|
+
from .grammar import (
|
|
20
26
|
parse,
|
|
21
27
|
)
|
|
22
28
|
|