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/registry.py
CHANGED
|
@@ -1,17 +1,35 @@
|
|
|
1
|
+
"""Registry and predicate logic for ABI encoders and decoders.
|
|
2
|
+
|
|
3
|
+
Implements registration, lookup, and matching of encoders and decoders for ABI type strings.
|
|
4
|
+
"""
|
|
1
5
|
import abc
|
|
2
|
-
import
|
|
6
|
+
from copy import (
|
|
7
|
+
copy,
|
|
8
|
+
)
|
|
3
9
|
import functools
|
|
4
10
|
from typing import (
|
|
5
11
|
Any,
|
|
6
12
|
Callable,
|
|
13
|
+
Dict,
|
|
14
|
+
Final,
|
|
15
|
+
Generic,
|
|
16
|
+
Iterator,
|
|
7
17
|
Optional,
|
|
8
18
|
Type,
|
|
19
|
+
TypeVar,
|
|
9
20
|
Union,
|
|
21
|
+
cast,
|
|
22
|
+
final,
|
|
10
23
|
)
|
|
11
24
|
|
|
12
25
|
from eth_typing import (
|
|
13
26
|
TypeStr,
|
|
14
27
|
)
|
|
28
|
+
from typing_extensions import (
|
|
29
|
+
Concatenate,
|
|
30
|
+
ParamSpec,
|
|
31
|
+
Self,
|
|
32
|
+
)
|
|
15
33
|
|
|
16
34
|
from . import (
|
|
17
35
|
decoding,
|
|
@@ -30,6 +48,9 @@ from .io import (
|
|
|
30
48
|
ContextFramesBytesIO,
|
|
31
49
|
)
|
|
32
50
|
|
|
51
|
+
T = TypeVar("T")
|
|
52
|
+
P = ParamSpec("P")
|
|
53
|
+
|
|
33
54
|
Lookup = Union[TypeStr, Callable[[TypeStr], bool]]
|
|
34
55
|
|
|
35
56
|
EncoderCallable = Callable[[Any], bytes]
|
|
@@ -41,44 +62,45 @@ Decoder = Union[DecoderCallable, Type[decoding.BaseDecoder]]
|
|
|
41
62
|
|
|
42
63
|
class Copyable(abc.ABC):
|
|
43
64
|
@abc.abstractmethod
|
|
44
|
-
def copy(self):
|
|
65
|
+
def copy(self) -> Self:
|
|
45
66
|
pass
|
|
46
67
|
|
|
47
|
-
def __copy__(self):
|
|
68
|
+
def __copy__(self) -> Self:
|
|
48
69
|
return self.copy()
|
|
49
70
|
|
|
50
|
-
def __deepcopy__(self, *args):
|
|
71
|
+
def __deepcopy__(self, *args: Any) -> Self:
|
|
51
72
|
return self.copy()
|
|
52
73
|
|
|
53
74
|
|
|
54
|
-
class PredicateMapping(Copyable):
|
|
75
|
+
class PredicateMapping(Copyable, Generic[T]):
|
|
55
76
|
"""
|
|
56
77
|
Acts as a mapping from predicate functions to values. Values are retrieved
|
|
57
78
|
when their corresponding predicate matches a given input. Predicates can
|
|
58
79
|
also be labeled to facilitate removal from the mapping.
|
|
59
80
|
"""
|
|
60
81
|
|
|
61
|
-
def __init__(self, name):
|
|
62
|
-
self._name = name
|
|
63
|
-
self._values = {}
|
|
64
|
-
self._labeled_predicates = {}
|
|
82
|
+
def __init__(self, name: str):
|
|
83
|
+
self._name: Final = name
|
|
84
|
+
self._values: Dict[Lookup, T] = {}
|
|
85
|
+
self._labeled_predicates: Dict[str, Lookup] = {}
|
|
65
86
|
|
|
66
|
-
def add(self, predicate, value, label=None):
|
|
87
|
+
def add(self, predicate: Lookup, value: T, label: Optional[str] = None) -> None:
|
|
67
88
|
if predicate in self._values:
|
|
68
89
|
raise ValueError(f"Matcher {predicate!r} already exists in {self._name}")
|
|
69
90
|
|
|
70
91
|
if label is not None:
|
|
71
|
-
|
|
92
|
+
labeled_predicates = self._labeled_predicates
|
|
93
|
+
if label in labeled_predicates:
|
|
72
94
|
raise ValueError(
|
|
73
95
|
f"Matcher {predicate!r} with label '{label}' "
|
|
74
96
|
f"already exists in {self._name}"
|
|
75
97
|
)
|
|
76
98
|
|
|
77
|
-
|
|
99
|
+
labeled_predicates[label] = predicate
|
|
78
100
|
|
|
79
101
|
self._values[predicate] = value
|
|
80
102
|
|
|
81
|
-
def find(self, type_str):
|
|
103
|
+
def find(self, type_str: TypeStr) -> T:
|
|
82
104
|
results = tuple(
|
|
83
105
|
(predicate, value)
|
|
84
106
|
for predicate, value in self._values.items()
|
|
@@ -103,9 +125,9 @@ class PredicateMapping(Copyable):
|
|
|
103
125
|
"documentation for more information."
|
|
104
126
|
)
|
|
105
127
|
|
|
106
|
-
return values[0]
|
|
128
|
+
return values[0] # type: ignore [no-any-return]
|
|
107
129
|
|
|
108
|
-
def remove_by_equality(self, predicate):
|
|
130
|
+
def remove_by_equality(self, predicate: Lookup) -> None:
|
|
109
131
|
# Delete the predicate mapping to the previously stored value
|
|
110
132
|
try:
|
|
111
133
|
del self._values[predicate]
|
|
@@ -120,7 +142,7 @@ class PredicateMapping(Copyable):
|
|
|
120
142
|
else:
|
|
121
143
|
del self._labeled_predicates[label]
|
|
122
144
|
|
|
123
|
-
def _label_for_predicate(self, predicate):
|
|
145
|
+
def _label_for_predicate(self, predicate: Lookup) -> str:
|
|
124
146
|
# Both keys and values in `_labeled_predicates` are unique since the
|
|
125
147
|
# `add` method enforces this
|
|
126
148
|
for key, value in self._labeled_predicates.items():
|
|
@@ -131,16 +153,17 @@ class PredicateMapping(Copyable):
|
|
|
131
153
|
f"Matcher {predicate!r} not referred to by any label in {self._name}"
|
|
132
154
|
)
|
|
133
155
|
|
|
134
|
-
def remove_by_label(self, label):
|
|
156
|
+
def remove_by_label(self, label: str) -> None:
|
|
157
|
+
labeled_predicates = self._labeled_predicates
|
|
135
158
|
try:
|
|
136
|
-
predicate =
|
|
159
|
+
predicate = labeled_predicates[label]
|
|
137
160
|
except KeyError:
|
|
138
161
|
raise KeyError(f"Label '{label}' not found in {self._name}")
|
|
139
162
|
|
|
140
|
-
del
|
|
163
|
+
del labeled_predicates[label]
|
|
141
164
|
del self._values[predicate]
|
|
142
165
|
|
|
143
|
-
def remove(self, predicate_or_label):
|
|
166
|
+
def remove(self, predicate_or_label: Union[Lookup, str]) -> None:
|
|
144
167
|
if callable(predicate_or_label):
|
|
145
168
|
self.remove_by_equality(predicate_or_label)
|
|
146
169
|
elif isinstance(predicate_or_label, str):
|
|
@@ -151,61 +174,79 @@ class PredicateMapping(Copyable):
|
|
|
151
174
|
f"{type(predicate_or_label)}"
|
|
152
175
|
)
|
|
153
176
|
|
|
154
|
-
def copy(self):
|
|
177
|
+
def copy(self) -> Self:
|
|
155
178
|
cpy = type(self)(self._name)
|
|
156
179
|
|
|
157
|
-
cpy._values = copy
|
|
158
|
-
cpy._labeled_predicates = copy
|
|
180
|
+
cpy._values = copy(self._values)
|
|
181
|
+
cpy._labeled_predicates = copy(self._labeled_predicates)
|
|
159
182
|
|
|
160
183
|
return cpy
|
|
161
184
|
|
|
162
185
|
|
|
163
|
-
class Predicate:
|
|
186
|
+
class Predicate(Generic[T]):
|
|
164
187
|
"""
|
|
165
188
|
Represents a predicate function to be used for type matching in
|
|
166
189
|
``ABIRegistry``.
|
|
167
190
|
"""
|
|
168
191
|
|
|
169
|
-
__slots__ =
|
|
192
|
+
__slots__ = ("_string", "__hash")
|
|
193
|
+
|
|
194
|
+
_string: Optional[str]
|
|
170
195
|
|
|
171
|
-
def
|
|
196
|
+
def __init__(self) -> None:
|
|
197
|
+
self._string = None
|
|
198
|
+
self.__hash = None
|
|
199
|
+
|
|
200
|
+
def __call__(self, arg: TypeStr) -> None:
|
|
172
201
|
raise NotImplementedError("Must implement `__call__`")
|
|
173
202
|
|
|
174
|
-
def __str__(self)
|
|
203
|
+
def __str__(self) -> str:
|
|
175
204
|
raise NotImplementedError("Must implement `__str__`")
|
|
176
205
|
|
|
177
|
-
def __repr__(self):
|
|
206
|
+
def __repr__(self) -> str:
|
|
178
207
|
return f"<{type(self).__name__} {self}>"
|
|
179
208
|
|
|
180
|
-
def __iter__(self):
|
|
181
|
-
|
|
182
|
-
yield getattr(self, attr)
|
|
209
|
+
def __iter__(self) -> Iterator[T]:
|
|
210
|
+
raise NotImplementedError("must be implemented by subclass")
|
|
183
211
|
|
|
184
|
-
def __hash__(self):
|
|
185
|
-
|
|
212
|
+
def __hash__(self) -> int:
|
|
213
|
+
hashval = self.__hash
|
|
214
|
+
if hashval is None:
|
|
215
|
+
self.__hash = hashval = hash(tuple(self))
|
|
216
|
+
return hashval
|
|
186
217
|
|
|
187
|
-
def __eq__(self, other):
|
|
218
|
+
def __eq__(self, other: "Predicate") -> bool:
|
|
188
219
|
return type(self) is type(other) and tuple(self) == tuple(other)
|
|
189
220
|
|
|
190
221
|
|
|
191
|
-
|
|
222
|
+
@final
|
|
223
|
+
class Equals(Predicate[str]):
|
|
192
224
|
"""
|
|
193
225
|
A predicate that matches any input equal to `value`.
|
|
194
226
|
"""
|
|
195
227
|
|
|
196
228
|
__slots__ = ("value",)
|
|
197
229
|
|
|
198
|
-
def __init__(self, value):
|
|
199
|
-
|
|
230
|
+
def __init__(self, value: str) -> None:
|
|
231
|
+
super().__init__()
|
|
232
|
+
self.value: Final = value
|
|
200
233
|
|
|
201
|
-
def __call__(self, other):
|
|
234
|
+
def __call__(self, other: TypeStr) -> bool:
|
|
202
235
|
return self.value == other
|
|
203
236
|
|
|
204
|
-
def __str__(self):
|
|
205
|
-
|
|
237
|
+
def __str__(self) -> str:
|
|
238
|
+
# NOTE should this just be done at init time? is it always called?
|
|
239
|
+
string = self._string
|
|
240
|
+
if string is None:
|
|
241
|
+
self._string = string = f"(== {self.value!r})"
|
|
242
|
+
return string
|
|
243
|
+
|
|
244
|
+
def __iter__(self) -> Iterator[str]:
|
|
245
|
+
yield self.value
|
|
206
246
|
|
|
207
247
|
|
|
208
|
-
|
|
248
|
+
@final
|
|
249
|
+
class BaseEquals(Predicate[Union[str, bool, None]]):
|
|
209
250
|
"""
|
|
210
251
|
A predicate that matches a basic type string with a base component equal to
|
|
211
252
|
`value` and no array component. If `with_sub` is `True`, the type string
|
|
@@ -216,11 +257,12 @@ class BaseEquals(Predicate):
|
|
|
216
257
|
|
|
217
258
|
__slots__ = ("base", "with_sub")
|
|
218
259
|
|
|
219
|
-
def __init__(self, base, *, with_sub=None):
|
|
220
|
-
|
|
221
|
-
self.
|
|
260
|
+
def __init__(self, base: TypeStr, *, with_sub: Optional[bool] = None):
|
|
261
|
+
super().__init__()
|
|
262
|
+
self.base: Final = base
|
|
263
|
+
self.with_sub: Final = with_sub
|
|
222
264
|
|
|
223
|
-
def __call__(self, type_str):
|
|
265
|
+
def __call__(self, type_str: TypeStr) -> bool:
|
|
224
266
|
try:
|
|
225
267
|
abi_type = grammar.parse(type_str)
|
|
226
268
|
except (exceptions.ParseError, ValueError):
|
|
@@ -230,10 +272,12 @@ class BaseEquals(Predicate):
|
|
|
230
272
|
if abi_type.arrlist is not None:
|
|
231
273
|
return False
|
|
232
274
|
|
|
233
|
-
|
|
234
|
-
|
|
275
|
+
with_sub = self.with_sub
|
|
276
|
+
if with_sub is not None:
|
|
277
|
+
abi_subtype = abi_type.sub
|
|
278
|
+
if with_sub and abi_subtype is None:
|
|
235
279
|
return False
|
|
236
|
-
if not
|
|
280
|
+
if not with_sub and abi_subtype is not None:
|
|
237
281
|
return False
|
|
238
282
|
|
|
239
283
|
return abi_type.base == self.base
|
|
@@ -242,19 +286,25 @@ class BaseEquals(Predicate):
|
|
|
242
286
|
# e.g. if it contained a tuple type
|
|
243
287
|
return False
|
|
244
288
|
|
|
245
|
-
def __str__(self):
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
289
|
+
def __str__(self) -> str:
|
|
290
|
+
# NOTE should this just be done at init time? is it always called?
|
|
291
|
+
string = self._string
|
|
292
|
+
if string is None:
|
|
293
|
+
if self.with_sub is None:
|
|
294
|
+
string = f"(base == {self.base!r})"
|
|
295
|
+
elif self.with_sub:
|
|
296
|
+
string = f"(base == {self.base!r} and sub is not None)"
|
|
297
|
+
else:
|
|
298
|
+
string = f"(base == {self.base!r} and sub is None)"
|
|
299
|
+
self._string = string
|
|
300
|
+
return string
|
|
301
|
+
|
|
302
|
+
def __iter__(self) -> Iterator[Union[str, bool, None]]:
|
|
303
|
+
yield self.base
|
|
304
|
+
yield self.with_sub
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def has_arrlist(type_str: TypeStr) -> bool:
|
|
258
308
|
"""
|
|
259
309
|
A predicate that matches a type string with an array dimension list.
|
|
260
310
|
"""
|
|
@@ -266,7 +316,7 @@ def has_arrlist(type_str):
|
|
|
266
316
|
return abi_type.arrlist is not None
|
|
267
317
|
|
|
268
318
|
|
|
269
|
-
def is_base_tuple(type_str):
|
|
319
|
+
def is_base_tuple(type_str: TypeStr) -> bool:
|
|
270
320
|
"""
|
|
271
321
|
A predicate that matches a tuple type with no array dimension list.
|
|
272
322
|
"""
|
|
@@ -278,19 +328,25 @@ def is_base_tuple(type_str):
|
|
|
278
328
|
return isinstance(abi_type, grammar.TupleType) and abi_type.arrlist is None
|
|
279
329
|
|
|
280
330
|
|
|
281
|
-
def _clear_encoder_cache(
|
|
331
|
+
def _clear_encoder_cache(
|
|
332
|
+
old_method: Callable[Concatenate["ABIRegistry", P], T]
|
|
333
|
+
) -> Callable[Concatenate["ABIRegistry", P], T]:
|
|
282
334
|
@functools.wraps(old_method)
|
|
283
|
-
def new_method(self: "ABIRegistry", *args:
|
|
335
|
+
def new_method(self: "ABIRegistry", *args: P.args, **kwargs: P.kwargs) -> T:
|
|
284
336
|
self.get_encoder.cache_clear()
|
|
337
|
+
self.get_tuple_encoder.cache_clear()
|
|
285
338
|
return old_method(self, *args, **kwargs)
|
|
286
339
|
|
|
287
340
|
return new_method
|
|
288
341
|
|
|
289
342
|
|
|
290
|
-
def _clear_decoder_cache(
|
|
343
|
+
def _clear_decoder_cache(
|
|
344
|
+
old_method: Callable[Concatenate["ABIRegistry", P], T]
|
|
345
|
+
) -> Callable[Concatenate["ABIRegistry", P], T]:
|
|
291
346
|
@functools.wraps(old_method)
|
|
292
|
-
def new_method(self: "ABIRegistry", *args:
|
|
347
|
+
def new_method(self: "ABIRegistry", *args: P.args, **kwargs: P.kwargs) -> T:
|
|
293
348
|
self.get_decoder.cache_clear()
|
|
349
|
+
self.get_tuple_decoder.cache_clear()
|
|
294
350
|
return old_method(self, *args, **kwargs)
|
|
295
351
|
|
|
296
352
|
return new_method
|
|
@@ -298,7 +354,12 @@ def _clear_decoder_cache(old_method: Callable[..., None]) -> Callable[..., None]
|
|
|
298
354
|
|
|
299
355
|
class BaseRegistry:
|
|
300
356
|
@staticmethod
|
|
301
|
-
def _register(
|
|
357
|
+
def _register(
|
|
358
|
+
mapping: PredicateMapping[T],
|
|
359
|
+
lookup: Lookup,
|
|
360
|
+
value: T,
|
|
361
|
+
label: Optional[str] = None,
|
|
362
|
+
) -> None:
|
|
302
363
|
if callable(lookup):
|
|
303
364
|
mapping.add(lookup, value, label)
|
|
304
365
|
return
|
|
@@ -312,7 +373,7 @@ class BaseRegistry:
|
|
|
312
373
|
)
|
|
313
374
|
|
|
314
375
|
@staticmethod
|
|
315
|
-
def _unregister(mapping, lookup_or_label):
|
|
376
|
+
def _unregister(mapping: PredicateMapping[Any], lookup_or_label: Lookup) -> None:
|
|
316
377
|
if callable(lookup_or_label):
|
|
317
378
|
mapping.remove_by_equality(lookup_or_label)
|
|
318
379
|
return
|
|
@@ -327,7 +388,7 @@ class BaseRegistry:
|
|
|
327
388
|
)
|
|
328
389
|
|
|
329
390
|
@staticmethod
|
|
330
|
-
def _get_registration(mapping, type_str):
|
|
391
|
+
def _get_registration(mapping: PredicateMapping[T], type_str: TypeStr) -> T:
|
|
331
392
|
try:
|
|
332
393
|
value = mapping.find(type_str)
|
|
333
394
|
except ValueError as e:
|
|
@@ -342,9 +403,9 @@ class BaseRegistry:
|
|
|
342
403
|
|
|
343
404
|
|
|
344
405
|
class ABIRegistry(Copyable, BaseRegistry):
|
|
345
|
-
def __init__(self):
|
|
346
|
-
self._encoders = PredicateMapping("encoder registry")
|
|
347
|
-
self._decoders = PredicateMapping("decoder registry")
|
|
406
|
+
def __init__(self) -> None:
|
|
407
|
+
self._encoders: PredicateMapping[Encoder] = PredicateMapping("encoder registry")
|
|
408
|
+
self._decoders: PredicateMapping[Decoder] = PredicateMapping("decoder registry")
|
|
348
409
|
self.get_encoder = functools.lru_cache(maxsize=None)(self._get_encoder_uncached)
|
|
349
410
|
self.get_decoder = functools.lru_cache(maxsize=None)(self._get_decoder_uncached)
|
|
350
411
|
self.get_tuple_encoder = functools.lru_cache(maxsize=None)(
|
|
@@ -354,13 +415,13 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
354
415
|
self._get_tuple_decoder_uncached
|
|
355
416
|
)
|
|
356
417
|
|
|
357
|
-
def _get_registration(self, mapping, type_str):
|
|
418
|
+
def _get_registration(self, mapping: PredicateMapping[T], type_str: TypeStr) -> T:
|
|
358
419
|
coder = super()._get_registration(mapping, type_str)
|
|
359
420
|
|
|
360
421
|
if isinstance(coder, type) and issubclass(coder, BaseCoder):
|
|
361
422
|
return coder.from_type_str(type_str, self)
|
|
362
423
|
|
|
363
|
-
return coder
|
|
424
|
+
return cast(T, coder)
|
|
364
425
|
|
|
365
426
|
@_clear_encoder_cache
|
|
366
427
|
def register_encoder(
|
|
@@ -460,16 +521,15 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
460
521
|
self.unregister_encoder(label)
|
|
461
522
|
self.unregister_decoder(label)
|
|
462
523
|
|
|
463
|
-
def _get_encoder_uncached(self, type_str: TypeStr)
|
|
524
|
+
def _get_encoder_uncached(self, type_str: TypeStr) -> Encoder:
|
|
464
525
|
return self._get_registration(self._encoders, type_str)
|
|
465
526
|
|
|
466
527
|
def _get_tuple_encoder_uncached(
|
|
467
|
-
self,
|
|
528
|
+
self,
|
|
468
529
|
*type_strs: TypeStr,
|
|
469
530
|
) -> encoding.TupleEncoder:
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
)
|
|
531
|
+
encoders = tuple(map(self.get_encoder, type_strs))
|
|
532
|
+
return encoding.TupleEncoder(encoders=encoders)
|
|
473
533
|
|
|
474
534
|
def has_encoder(self, type_str: TypeStr) -> bool:
|
|
475
535
|
"""
|
|
@@ -487,7 +547,7 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
487
547
|
|
|
488
548
|
return True
|
|
489
549
|
|
|
490
|
-
def _get_decoder_uncached(self, type_str: TypeStr, strict: bool = True)
|
|
550
|
+
def _get_decoder_uncached(self, type_str: TypeStr, strict: bool = True) -> Decoder:
|
|
491
551
|
decoder = self._get_registration(self._decoders, type_str)
|
|
492
552
|
|
|
493
553
|
if hasattr(decoder, "is_dynamic") and decoder.is_dynamic:
|
|
@@ -499,15 +559,17 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
499
559
|
return decoder
|
|
500
560
|
|
|
501
561
|
def _get_tuple_decoder_uncached(
|
|
502
|
-
self,
|
|
503
|
-
*type_strs: TypeStr,
|
|
562
|
+
self,
|
|
563
|
+
*type_strs: TypeStr,
|
|
504
564
|
strict: bool = True,
|
|
505
565
|
) -> decoding.TupleDecoder:
|
|
506
|
-
|
|
507
|
-
|
|
566
|
+
decoders = tuple(
|
|
567
|
+
self.get_decoder(type_str, strict)
|
|
568
|
+
for type_str in type_strs
|
|
508
569
|
)
|
|
570
|
+
return decoding.TupleDecoder(decoders=decoders)
|
|
509
571
|
|
|
510
|
-
def copy(self):
|
|
572
|
+
def copy(self) -> Self:
|
|
511
573
|
"""
|
|
512
574
|
Copies a registry such that new registrations can be made or existing
|
|
513
575
|
registrations can be unregistered without affecting any instance from
|
|
@@ -518,22 +580,43 @@ class ABIRegistry(Copyable, BaseRegistry):
|
|
|
518
580
|
"""
|
|
519
581
|
cpy = type(self)()
|
|
520
582
|
|
|
521
|
-
cpy._encoders = copy
|
|
522
|
-
cpy._decoders = copy
|
|
583
|
+
cpy._encoders = copy(self._encoders)
|
|
584
|
+
cpy._decoders = copy(self._decoders)
|
|
523
585
|
|
|
524
586
|
return cpy
|
|
525
587
|
|
|
526
588
|
|
|
527
589
|
registry = ABIRegistry()
|
|
528
590
|
|
|
591
|
+
is_int = BaseEquals("int")
|
|
592
|
+
is_int8 = Equals("int8")
|
|
593
|
+
is_int16 = Equals("int16")
|
|
594
|
+
is_uint = BaseEquals("uint")
|
|
595
|
+
is_uint8 = Equals("uint8")
|
|
596
|
+
is_uint16 = Equals("uint16")
|
|
597
|
+
|
|
598
|
+
for size in (8, 16):
|
|
599
|
+
registry.register(
|
|
600
|
+
Equals(f"uint{size}"),
|
|
601
|
+
encoding.UnsignedIntegerEncoder,
|
|
602
|
+
decoding.UnsignedIntegerDecoder,
|
|
603
|
+
label=f"uint{size}",
|
|
604
|
+
)
|
|
605
|
+
registry.register(
|
|
606
|
+
Equals(f"int{size}"),
|
|
607
|
+
encoding.SignedIntegerEncoder,
|
|
608
|
+
decoding.SignedIntegerDecoder,
|
|
609
|
+
label=f"int{size}",
|
|
610
|
+
)
|
|
611
|
+
|
|
529
612
|
registry.register(
|
|
530
|
-
|
|
613
|
+
lambda s: is_uint(s) and not is_uint8(s) and not is_uint16(s),
|
|
531
614
|
encoding.UnsignedIntegerEncoder,
|
|
532
615
|
decoding.UnsignedIntegerDecoder,
|
|
533
616
|
label="uint",
|
|
534
617
|
)
|
|
535
618
|
registry.register(
|
|
536
|
-
|
|
619
|
+
lambda s: is_int(s) and not is_int8(s) and not is_int16(s),
|
|
537
620
|
encoding.SignedIntegerEncoder,
|
|
538
621
|
decoding.SignedIntegerDecoder,
|
|
539
622
|
label="int",
|
|
@@ -601,13 +684,25 @@ registry.register(
|
|
|
601
684
|
|
|
602
685
|
registry_packed = ABIRegistry()
|
|
603
686
|
|
|
687
|
+
for size in (8, 16):
|
|
688
|
+
registry_packed.register_encoder(
|
|
689
|
+
Equals(f"uint{size}"),
|
|
690
|
+
encoding.PackedUnsignedIntegerEncoderCached,
|
|
691
|
+
label=f"uint{size}",
|
|
692
|
+
)
|
|
693
|
+
registry_packed.register_encoder(
|
|
694
|
+
Equals(f"int{size}"),
|
|
695
|
+
encoding.PackedSignedIntegerEncoderCached,
|
|
696
|
+
label=f"int{size}",
|
|
697
|
+
)
|
|
698
|
+
|
|
604
699
|
registry_packed.register_encoder(
|
|
605
|
-
|
|
700
|
+
lambda s: is_uint(s) and not is_uint8(s) and not is_uint16(s),
|
|
606
701
|
encoding.PackedUnsignedIntegerEncoder,
|
|
607
702
|
label="uint",
|
|
608
703
|
)
|
|
609
704
|
registry_packed.register_encoder(
|
|
610
|
-
|
|
705
|
+
lambda s: is_int(s) and not is_int8(s) and not is_int16(s),
|
|
611
706
|
encoding.PackedSignedIntegerEncoder,
|
|
612
707
|
label="int",
|
|
613
708
|
)
|
|
Binary file
|
|
Binary file
|
|
@@ -2,7 +2,9 @@ from typing import (
|
|
|
2
2
|
Callable,
|
|
3
3
|
Final,
|
|
4
4
|
Optional,
|
|
5
|
+
Tuple,
|
|
5
6
|
Union,
|
|
7
|
+
cast,
|
|
6
8
|
)
|
|
7
9
|
|
|
8
10
|
from cchecksum import (
|
|
@@ -15,11 +17,14 @@ from hypothesis import (
|
|
|
15
17
|
strategies as st,
|
|
16
18
|
)
|
|
17
19
|
|
|
18
|
-
from faster_eth_abi.
|
|
20
|
+
from faster_eth_abi._grammar import (
|
|
19
21
|
ABIType,
|
|
22
|
+
Arrlist,
|
|
20
23
|
BasicType,
|
|
21
24
|
TupleType,
|
|
22
25
|
normalize,
|
|
26
|
+
)
|
|
27
|
+
from faster_eth_abi.grammar import (
|
|
23
28
|
parse,
|
|
24
29
|
)
|
|
25
30
|
from faster_eth_abi.registry import (
|
|
@@ -81,7 +86,7 @@ class StrategyRegistry(BaseRegistry):
|
|
|
81
86
|
def get_uint_strategy(
|
|
82
87
|
abi_type: BasicType, registry: StrategyRegistry
|
|
83
88
|
) -> st.SearchStrategy:
|
|
84
|
-
bits = abi_type.sub
|
|
89
|
+
bits = cast(int, abi_type.sub)
|
|
85
90
|
|
|
86
91
|
return st.integers(
|
|
87
92
|
min_value=0,
|
|
@@ -92,7 +97,7 @@ def get_uint_strategy(
|
|
|
92
97
|
def get_int_strategy(
|
|
93
98
|
abi_type: BasicType, registry: StrategyRegistry
|
|
94
99
|
) -> st.SearchStrategy:
|
|
95
|
-
bits = abi_type.sub
|
|
100
|
+
bits = cast(int, abi_type.sub)
|
|
96
101
|
|
|
97
102
|
return st.integers(
|
|
98
103
|
min_value=-(2 ** (bits - 1)),
|
|
@@ -107,7 +112,7 @@ bool_strategy: Final = st.booleans()
|
|
|
107
112
|
def get_ufixed_strategy(
|
|
108
113
|
abi_type: BasicType, registry: StrategyRegistry
|
|
109
114
|
) -> st.SearchStrategy:
|
|
110
|
-
bits, places = abi_type.sub
|
|
115
|
+
bits, places = cast(Tuple[int, int], abi_type.sub)
|
|
111
116
|
|
|
112
117
|
return st.decimals(
|
|
113
118
|
min_value=0,
|
|
@@ -119,7 +124,7 @@ def get_ufixed_strategy(
|
|
|
119
124
|
def get_fixed_strategy(
|
|
120
125
|
abi_type: BasicType, registry: StrategyRegistry
|
|
121
126
|
) -> st.SearchStrategy:
|
|
122
|
-
bits, places = abi_type.sub
|
|
127
|
+
bits, places = cast(Tuple[int, int], abi_type.sub)
|
|
123
128
|
|
|
124
129
|
return st.decimals(
|
|
125
130
|
min_value=-(2 ** (bits - 1)),
|
|
@@ -150,7 +155,8 @@ def get_array_strategy(
|
|
|
150
155
|
item_type_str = item_type.to_type_str()
|
|
151
156
|
item_strategy = registry.get_strategy(item_type_str)
|
|
152
157
|
|
|
153
|
-
|
|
158
|
+
arrlist = cast(Arrlist, abi_type.arrlist)
|
|
159
|
+
last_dim = cast(Tuple[int, ...], arrlist[-1])
|
|
154
160
|
if len(last_dim) == 0:
|
|
155
161
|
# Is dynamic list. Don't restrict length.
|
|
156
162
|
return st.lists(item_strategy)
|