xref: /linux/tools/net/sunrpc/xdrgen/generators/struct.py (revision c34e9ab9a612ee8b18273398ef75c207b01f516d)
1#!/usr/bin/env python3
2# ex: set filetype=python:
3
4"""Generate code to handle XDR struct types"""
5
6from jinja2 import Environment
7
8from generators import SourceGenerator, kernel_c_type
9from generators import create_jinja2_environment, get_jinja2_template
10
11from xdr_ast import _XdrBasic, _XdrString
12from xdr_ast import _XdrFixedLengthOpaque, _XdrVariableLengthOpaque
13from xdr_ast import _XdrFixedLengthArray, _XdrVariableLengthArray
14from xdr_ast import _XdrOptionalData, _XdrStruct, _XdrDeclaration
15from xdr_ast import public_apis, get_header_name
16
17
18def emit_struct_declaration(environment: Environment, node: _XdrStruct) -> None:
19    """Emit one declaration pair for an XDR struct type"""
20    if node.name in public_apis:
21        template = get_jinja2_template(environment, "declaration", "close")
22        print(template.render(name=node.name))
23
24
25def emit_struct_member_definition(
26    environment: Environment, field: _XdrDeclaration
27) -> None:
28    """Emit a definition for one field in an XDR struct"""
29    if isinstance(field, _XdrBasic):
30        template = get_jinja2_template(environment, "definition", field.template)
31        print(
32            template.render(
33                name=field.name,
34                type=kernel_c_type(field.spec),
35                classifier=field.spec.c_classifier,
36            )
37        )
38    elif isinstance(field, _XdrFixedLengthOpaque):
39        template = get_jinja2_template(environment, "definition", field.template)
40        print(
41            template.render(
42                name=field.name,
43                size=field.size,
44            )
45        )
46    elif isinstance(field, _XdrVariableLengthOpaque):
47        template = get_jinja2_template(environment, "definition", field.template)
48        print(template.render(name=field.name))
49    elif isinstance(field, _XdrString):
50        template = get_jinja2_template(environment, "definition", field.template)
51        print(template.render(name=field.name))
52    elif isinstance(field, _XdrFixedLengthArray):
53        template = get_jinja2_template(environment, "definition", field.template)
54        print(
55            template.render(
56                name=field.name,
57                type=kernel_c_type(field.spec),
58                size=field.size,
59            )
60        )
61    elif isinstance(field, _XdrVariableLengthArray):
62        template = get_jinja2_template(environment, "definition", field.template)
63        print(
64            template.render(
65                name=field.name,
66                type=kernel_c_type(field.spec),
67                classifier=field.spec.c_classifier,
68            )
69        )
70    elif isinstance(field, _XdrOptionalData):
71        template = get_jinja2_template(environment, "definition", field.template)
72        print(
73            template.render(
74                name=field.name,
75                type=kernel_c_type(field.spec),
76                classifier=field.spec.c_classifier,
77            )
78        )
79
80
81def emit_struct_definition(environment: Environment, node: _XdrStruct) -> None:
82    """Emit one definition for an XDR struct type"""
83    template = get_jinja2_template(environment, "definition", "open")
84    print(template.render(name=node.name))
85
86    for field in node.fields:
87        emit_struct_member_definition(environment, field)
88
89    template = get_jinja2_template(environment, "definition", "close")
90    print(template.render(name=node.name))
91
92
93def emit_struct_member_decoder(
94    environment: Environment, field: _XdrDeclaration
95) -> None:
96    """Emit a decoder for one field in an XDR struct"""
97    if isinstance(field, _XdrBasic):
98        template = get_jinja2_template(environment, "decoder", field.template)
99        print(
100            template.render(
101                name=field.name,
102                type=field.spec.type_name,
103                classifier=field.spec.c_classifier,
104            )
105        )
106    elif isinstance(field, _XdrFixedLengthOpaque):
107        template = get_jinja2_template(environment, "decoder", field.template)
108        print(
109            template.render(
110                name=field.name,
111                size=field.size,
112            )
113        )
114    elif isinstance(field, _XdrVariableLengthOpaque):
115        template = get_jinja2_template(environment, "decoder", field.template)
116        print(
117            template.render(
118                name=field.name,
119                maxsize=field.maxsize,
120            )
121        )
122    elif isinstance(field, _XdrString):
123        template = get_jinja2_template(environment, "decoder", field.template)
124        print(
125            template.render(
126                name=field.name,
127                maxsize=field.maxsize,
128            )
129        )
130    elif isinstance(field, _XdrFixedLengthArray):
131        template = get_jinja2_template(environment, "decoder", field.template)
132        print(
133            template.render(
134                name=field.name,
135                type=field.spec.type_name,
136                size=field.size,
137                classifier=field.spec.c_classifier,
138            )
139        )
140    elif isinstance(field, _XdrVariableLengthArray):
141        template = get_jinja2_template(environment, "decoder", field.template)
142        print(
143            template.render(
144                name=field.name,
145                type=field.spec.type_name,
146                maxsize=field.maxsize,
147                classifier=field.spec.c_classifier,
148            )
149        )
150    elif isinstance(field, _XdrOptionalData):
151        template = get_jinja2_template(environment, "decoder", field.template)
152        print(
153            template.render(
154                name=field.name,
155                type=field.spec.type_name,
156                classifier=field.spec.c_classifier,
157            )
158        )
159
160
161def emit_struct_decoder(environment: Environment, node: _XdrStruct) -> None:
162    """Emit one decoder function for an XDR struct type"""
163    template = get_jinja2_template(environment, "decoder", "open")
164    print(template.render(name=node.name))
165
166    for field in node.fields:
167        emit_struct_member_decoder(environment, field)
168
169    template = get_jinja2_template(environment, "decoder", "close")
170    print(template.render())
171
172
173def emit_struct_member_encoder(
174    environment: Environment, field: _XdrDeclaration
175) -> None:
176    """Emit an encoder for one field in an XDR struct"""
177    if isinstance(field, _XdrBasic):
178        template = get_jinja2_template(environment, "encoder", field.template)
179        print(
180            template.render(
181                name=field.name,
182                type=field.spec.type_name,
183            )
184        )
185    elif isinstance(field, _XdrFixedLengthOpaque):
186        template = get_jinja2_template(environment, "encoder", field.template)
187        print(
188            template.render(
189                name=field.name,
190                size=field.size,
191            )
192        )
193    elif isinstance(field, _XdrVariableLengthOpaque):
194        template = get_jinja2_template(environment, "encoder", field.template)
195        print(
196            template.render(
197                name=field.name,
198                maxsize=field.maxsize,
199            )
200        )
201    elif isinstance(field, _XdrString):
202        template = get_jinja2_template(environment, "encoder", field.template)
203        print(
204            template.render(
205                name=field.name,
206                maxsize=field.maxsize,
207            )
208        )
209    elif isinstance(field, _XdrFixedLengthArray):
210        template = get_jinja2_template(environment, "encoder", field.template)
211        print(
212            template.render(
213                name=field.name,
214                type=field.spec.type_name,
215                size=field.size,
216            )
217        )
218    elif isinstance(field, _XdrVariableLengthArray):
219        template = get_jinja2_template(environment, "encoder", field.template)
220        print(
221            template.render(
222                name=field.name,
223                type=field.spec.type_name,
224                maxsize=field.maxsize,
225            )
226        )
227    elif isinstance(field, _XdrOptionalData):
228        template = get_jinja2_template(environment, "encoder", field.template)
229        print(
230            template.render(
231                name=field.name,
232                type=field.spec.type_name,
233                classifier=field.spec.c_classifier,
234            )
235        )
236
237
238def emit_struct_encoder(environment: Environment, node: _XdrStruct) -> None:
239    """Emit one encoder function for an XDR struct type"""
240    template = get_jinja2_template(environment, "encoder", "open")
241    print(template.render(name=node.name))
242
243    for field in node.fields:
244        emit_struct_member_encoder(environment, field)
245
246    template = get_jinja2_template(environment, "encoder", "close")
247    print(template.render())
248
249
250def emit_struct_maxsize(environment: Environment, node: _XdrStruct) -> None:
251    """Emit one maxsize macro for an XDR struct type"""
252    macro_name = get_header_name().upper() + "_" + node.name + "_sz"
253    template = get_jinja2_template(environment, "maxsize", "struct")
254    print(
255        template.render(
256            macro=macro_name,
257            width=" + ".join(node.symbolic_width()),
258        )
259    )
260
261
262class XdrStructGenerator(SourceGenerator):
263    """Generate source code for XDR structs"""
264
265    def __init__(self, language: str, peer: str):
266        """Initialize an instance of this class"""
267        self.environment = create_jinja2_environment(language, "struct")
268        self.peer = peer
269
270    def emit_declaration(self, node: _XdrStruct) -> None:
271        """Emit one declaration pair for an XDR struct type"""
272        emit_struct_declaration(self.environment, node)
273
274    def emit_definition(self, node: _XdrStruct) -> None:
275        """Emit one definition for an XDR struct type"""
276        emit_struct_definition(self.environment, node)
277
278    def emit_decoder(self, node: _XdrStruct) -> None:
279        """Emit one decoder function for an XDR struct type"""
280        emit_struct_decoder(self.environment, node)
281
282    def emit_encoder(self, node: _XdrStruct) -> None:
283        """Emit one encoder function for an XDR struct type"""
284        emit_struct_encoder(self.environment, node)
285
286    def emit_maxsize(self, node: _XdrStruct) -> None:
287        """Emit one maxsize macro for an XDR struct type"""
288        emit_struct_maxsize(self.environment, node)
289