4
4
5
5
import io
6
6
import logging
7
+ import re
7
8
from enum import Enum
8
9
from textwrap import dedent , indent
9
10
from typing import TYPE_CHECKING , Iterator , Optional
47
48
WcharArray ,
48
49
)
49
50
51
+ RE_TYPE_LOOKUP = re .compile (r"lookup\[[\"\'](.+?)[\"\']\].type" )
52
+
50
53
log = logging .getLogger (__name__ )
51
54
52
55
python_compile = compile
@@ -58,7 +61,7 @@ def compile(structure: type[Structure]) -> type[Structure]:
58
61
59
62
try :
60
63
structure ._read = classmethod (
61
- generate_read (structure .cs , structure .fields , structure .__name__ , structure .align )
64
+ generate_read (structure .cs , structure .fields , structure .__lookup__ , structure . __name__ , structure .align )
62
65
)
63
66
structure .__compiled__ = True
64
67
except Exception as e :
@@ -68,11 +71,26 @@ def compile(structure: type[Structure]) -> type[Structure]:
68
71
return structure
69
72
70
73
71
- def generate_read (cs : cstruct , fields : list [Field ], name : Optional [str ] = None , align : bool = False ) -> Iterator [str ]:
74
+ def generate_read (
75
+ cs : cstruct , fields : list [Field ], lookup , name : Optional [str ] = None , align : bool = False
76
+ ) -> Iterator [str ]:
72
77
source = generate_read_source (cs , fields , align )
73
78
74
- code = python_compile (source , f"<compiled { name or 'anonymous' } >" , "exec" )
75
- exec (code , {"BitBuffer" : BitBuffer , "_struct" : _struct }, d := {})
79
+ token_id = 0
80
+ token_map = {}
81
+
82
+ def _replace_token (match ):
83
+ nonlocal token_id
84
+ token = f"_{ token_id } "
85
+ token_map [token ] = match .group (1 )
86
+ token_id += 1
87
+ return token
88
+
89
+ source = re .sub (RE_TYPE_LOOKUP , _replace_token , source )
90
+ symbols = {token : lookup [field_name ].type for token , field_name in token_map .items ()}
91
+
92
+ code = python_compile (source , f"<compiled { name or 'anonymous' } ._read>" , "exec" )
93
+ exec (code , {"BitBuffer" : BitBuffer , "_struct" : _struct , ** symbols }, d := {})
76
94
obj = d .popitem ()[1 ]
77
95
obj .__source__ = source
78
96
@@ -83,7 +101,6 @@ def generate_read_source(cs: cstruct, fields: list[Field], align: bool = False)
83
101
preamble = """
84
102
r = {}
85
103
s = {}
86
- lookup = cls.__lookup__
87
104
"""
88
105
89
106
if any (field .bits for field in fields ):
@@ -92,7 +109,7 @@ def generate_read_source(cs: cstruct, fields: list[Field], align: bool = False)
92
109
read_code = "\n " .join (generate_fields_read (cs , fields , align ))
93
110
94
111
outro = """
95
- obj = cls( **r)
112
+ obj = type.__call__(cls, **r)
96
113
obj._sizes = s
97
114
obj._values = r
98
115
0 commit comments