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