1#!/usr/bin/env python3
2# ex: set filetype=python:
3
4"""Generate code to handle XDR typedefs"""
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, _XdrTypedef, _XdrVariableLengthString
12from xdr_ast import _XdrFixedLengthOpaque, _XdrVariableLengthOpaque
13from xdr_ast import _XdrFixedLengthArray, _XdrVariableLengthArray
14from xdr_ast import _XdrOptionalData, _XdrVoid, _XdrDeclaration
15from xdr_ast import public_apis
16
17
18def emit_typedef_declaration(environment: Environment, node: _XdrDeclaration) -> None:
19    """Emit a declaration pair for one XDR typedef"""
20    if node.name not in public_apis:
21        return
22    if isinstance(node, _XdrBasic):
23        template = get_jinja2_template(environment, "declaration", node.template)
24        print(
25            template.render(
26                name=node.name,
27                type=kernel_c_type(node.spec),
28                classifier=node.spec.c_classifier,
29            )
30        )
31    elif isinstance(node, _XdrVariableLengthString):
32        template = get_jinja2_template(environment, "declaration", node.template)
33        print(template.render(name=node.name))
34    elif isinstance(node, _XdrFixedLengthOpaque):
35        template = get_jinja2_template(environment, "declaration", node.template)
36        print(template.render(name=node.name, size=node.size))
37    elif isinstance(node, _XdrVariableLengthOpaque):
38        template = get_jinja2_template(environment, "declaration", node.template)
39        print(template.render(name=node.name))
40    elif isinstance(node, _XdrFixedLengthArray):
41        template = get_jinja2_template(environment, "declaration", node.template)
42        print(
43            template.render(
44                name=node.name,
45                type=node.spec.type_name,
46                size=node.size,
47            )
48        )
49    elif isinstance(node, _XdrVariableLengthArray):
50        template = get_jinja2_template(environment, "declaration", node.template)
51        print(
52            template.render(
53                name=node.name,
54                type=node.spec.type_name,
55                classifier=node.spec.c_classifier,
56            )
57        )
58    elif isinstance(node, _XdrOptionalData):
59        raise NotImplementedError("<optional_data> typedef not yet implemented")
60    elif isinstance(node, _XdrVoid):
61        raise NotImplementedError("<void> typedef not yet implemented")
62    else:
63        raise NotImplementedError("typedef: type not recognized")
64
65
66def emit_type_definition(environment: Environment, node: _XdrDeclaration) -> None:
67    """Emit a definition for one XDR typedef"""
68    if isinstance(node, _XdrBasic):
69        template = get_jinja2_template(environment, "definition", node.template)
70        print(
71            template.render(
72                name=node.name,
73                type=kernel_c_type(node.spec),
74                classifier=node.spec.c_classifier,
75            )
76        )
77    elif isinstance(node, _XdrVariableLengthString):
78        template = get_jinja2_template(environment, "definition", node.template)
79        print(template.render(name=node.name))
80    elif isinstance(node, _XdrFixedLengthOpaque):
81        template = get_jinja2_template(environment, "definition", node.template)
82        print(template.render(name=node.name, size=node.size))
83    elif isinstance(node, _XdrVariableLengthOpaque):
84        template = get_jinja2_template(environment, "definition", node.template)
85        print(template.render(name=node.name))
86    elif isinstance(node, _XdrFixedLengthArray):
87        template = get_jinja2_template(environment, "definition", node.template)
88        print(
89            template.render(
90                name=node.name,
91                type=node.spec.type_name,
92                size=node.size,
93            )
94        )
95    elif isinstance(node, _XdrVariableLengthArray):
96        template = get_jinja2_template(environment, "definition", node.template)
97        print(
98            template.render(
99                name=node.name,
100                type=node.spec.type_name,
101                classifier=node.spec.c_classifier,
102            )
103        )
104    elif isinstance(node, _XdrOptionalData):
105        raise NotImplementedError("<optional_data> typedef not yet implemented")
106    elif isinstance(node, _XdrVoid):
107        raise NotImplementedError("<void> typedef not yet implemented")
108    else:
109        raise NotImplementedError("typedef: type not recognized")
110
111
112def emit_typedef_decoder(environment: Environment, node: _XdrDeclaration) -> None:
113    """Emit a decoder function for one XDR typedef"""
114    if isinstance(node, _XdrBasic):
115        template = get_jinja2_template(environment, "decoder", node.template)
116        print(
117            template.render(
118                name=node.name,
119                type=node.spec.type_name,
120            )
121        )
122    elif isinstance(node, _XdrVariableLengthString):
123        template = get_jinja2_template(environment, "decoder", node.template)
124        print(
125            template.render(
126                name=node.name,
127                maxsize=node.maxsize,
128            )
129        )
130    elif isinstance(node, _XdrFixedLengthOpaque):
131        template = get_jinja2_template(environment, "decoder", node.template)
132        print(
133            template.render(
134                name=node.name,
135                size=node.size,
136            )
137        )
138    elif isinstance(node, _XdrVariableLengthOpaque):
139        template = get_jinja2_template(environment, "decoder", node.template)
140        print(
141            template.render(
142                name=node.name,
143                maxsize=node.maxsize,
144            )
145        )
146    elif isinstance(node, _XdrFixedLengthArray):
147        template = get_jinja2_template(environment, "decoder", node.template)
148        print(
149            template.render(
150                name=node.name,
151                type=node.spec.type_name,
152                size=node.size,
153                classifier=node.spec.c_classifier,
154            )
155        )
156    elif isinstance(node, _XdrVariableLengthArray):
157        template = get_jinja2_template(environment, "decoder", node.template)
158        print(
159            template.render(
160                name=node.name,
161                type=node.spec.type_name,
162                maxsize=node.maxsize,
163            )
164        )
165    elif isinstance(node, _XdrOptionalData):
166        raise NotImplementedError("<optional_data> typedef not yet implemented")
167    elif isinstance(node, _XdrVoid):
168        raise NotImplementedError("<void> typedef not yet implemented")
169    else:
170        raise NotImplementedError("typedef: type not recognized")
171
172
173def emit_typedef_encoder(environment: Environment, node: _XdrDeclaration) -> None:
174    """Emit an encoder function for one XDR typedef"""
175    if isinstance(node, _XdrBasic):
176        template = get_jinja2_template(environment, "encoder", node.template)
177        print(
178            template.render(
179                name=node.name,
180                type=node.spec.type_name,
181            )
182        )
183    elif isinstance(node, _XdrVariableLengthString):
184        template = get_jinja2_template(environment, "encoder", node.template)
185        print(
186            template.render(
187                name=node.name,
188                maxsize=node.maxsize,
189            )
190        )
191    elif isinstance(node, _XdrFixedLengthOpaque):
192        template = get_jinja2_template(environment, "encoder", node.template)
193        print(
194            template.render(
195                name=node.name,
196                size=node.size,
197            )
198        )
199    elif isinstance(node, _XdrVariableLengthOpaque):
200        template = get_jinja2_template(environment, "encoder", node.template)
201        print(
202            template.render(
203                name=node.name,
204                maxsize=node.maxsize,
205            )
206        )
207    elif isinstance(node, _XdrFixedLengthArray):
208        template = get_jinja2_template(environment, "encoder", node.template)
209        print(
210            template.render(
211                name=node.name,
212                type=node.spec.type_name,
213                size=node.size,
214            )
215        )
216    elif isinstance(node, _XdrVariableLengthArray):
217        template = get_jinja2_template(environment, "encoder", node.template)
218        print(
219            template.render(
220                name=node.name,
221                type=node.spec.type_name,
222                maxsize=node.maxsize,
223            )
224        )
225    elif isinstance(node, _XdrOptionalData):
226        raise NotImplementedError("<optional_data> typedef not yet implemented")
227    elif isinstance(node, _XdrVoid):
228        raise NotImplementedError("<void> typedef not yet implemented")
229    else:
230        raise NotImplementedError("typedef: type not recognized")
231
232
233class XdrTypedefGenerator(SourceGenerator):
234    """Generate source code for XDR typedefs"""
235
236    def __init__(self, language: str, peer: str):
237        """Initialize an instance of this class"""
238        self.environment = create_jinja2_environment(language, "typedef")
239        self.peer = peer
240
241    def emit_declaration(self, node: _XdrTypedef) -> None:
242        """Emit one declaration pair for an XDR enum type"""
243        emit_typedef_declaration(self.environment, node.declaration)
244
245    def emit_definition(self, node: _XdrTypedef) -> None:
246        """Emit one definition for an XDR typedef"""
247        emit_type_definition(self.environment, node.declaration)
248
249    def emit_decoder(self, node: _XdrTypedef) -> None:
250        """Emit one decoder function for an XDR typedef"""
251        emit_typedef_decoder(self.environment, node.declaration)
252
253    def emit_encoder(self, node: _XdrTypedef) -> None:
254        """Emit one encoder function for an XDR typedef"""
255        emit_typedef_encoder(self.environment, node.declaration)
256