github.com/osrg/gobgp/v3@v3.30.0/tools/pyang_plugins/bgpyang2golang.py (about) 1 # Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 # implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 16 from __future__ import print_function 17 18 import sys 19 from collections import namedtuple 20 21 from pyang import plugin 22 23 _COPYRIGHT_NOTICE = """ 24 // DO NOT EDIT 25 // generated by pyang using OpenConfig https://github.com/openconfig/public 26 // 27 // Copyright (C) 2014-2019 Nippon Telegraph and Telephone Corporation. 28 // 29 // Licensed under the Apache License, Version 2.0 (the "License"); 30 // you may not use this file except in compliance with the License. 31 // You may obtain a copy of the License at 32 // 33 // http://www.apache.org/licenses/LICENSE-2.0 34 // 35 // Unless required by applicable law or agreed to in writing, software 36 // distributed under the License is distributed on an "AS IS" BASIS, 37 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 38 // implied. 39 // See the License for the specific language governing permissions and 40 // limitations under the License. 41 42 // Code generated by pyang. DO NOT EDIT. 43 """ 44 45 EQUAL_TYPE_LEAF = 0 46 EQUAL_TYPE_ARRAY = 1 47 EQUAL_TYPE_MAP = 2 48 EQUAL_TYPE_CONTAINER = 3 49 50 51 def pyang_plugin_init(): 52 plugin.register_plugin(GolangPlugin()) 53 54 55 class GolangPlugin(plugin.PyangPlugin): 56 57 def __init__(self, name=None): 58 super(GolangPlugin, self).__init__(name=name) 59 self.multiple_modules = True 60 61 def add_output_format(self, fmts): 62 fmts['golang'] = self 63 64 def emit(self, ctx, modules, fd): 65 ctx.golang_identity_map = {} 66 ctx.golang_typedef_map = {} 67 ctx.golang_struct_def = [] 68 ctx.golang_struct_names = {} 69 70 ctx.emitted_type_names = {} 71 72 ctx.prefix_rel = {} 73 ctx.module_deps = [] 74 for m in modules: 75 check_module_deps(ctx, m) 76 77 # visit yang statements 78 visit_modules(ctx) 79 80 # emit bgp_configs 81 emit_go(ctx, fd) 82 83 84 def visit_modules(ctx): 85 # visit typedef and identity 86 for mod in ctx.module_deps: 87 visit_typedef(ctx, mod) 88 visit_identity(ctx, mod) 89 90 # visit container 91 for mod in ctx.module_deps: 92 visit_children(ctx, mod, mod.i_children) 93 94 95 def emit_go(ctx, fd): 96 ctx.golang_struct_def.reverse() 97 done = set() 98 99 # emit 100 generate_header(fd) 101 generate_common_functions(fd) 102 103 for mod in ctx.module_deps: 104 if mod not in _module_excluded: 105 emit_typedef(ctx, mod, fd) 106 emit_identity(ctx, mod, fd) 107 108 for struct in ctx.golang_struct_def: 109 struct_name = struct.uniq_name 110 if struct_name in done: 111 continue 112 emit_class_def(ctx, struct, struct_name, struct.module_prefix, fd) 113 done.add(struct_name) 114 115 116 def check_module_deps(ctx, mod): 117 own_prefix = mod.i_prefix 118 for k, v in mod.i_prefixes.items(): 119 mod = ctx.get_module(v[0]) 120 if mod is None: 121 continue 122 123 if mod.i_prefix != own_prefix: 124 check_module_deps(ctx, mod) 125 126 ctx.prefix_rel[mod.i_prefix] = k 127 if (mod not in ctx.module_deps 128 and mod.i_modulename not in _module_excluded): 129 ctx.module_deps.append(mod) 130 131 132 def dig_leafref(type_obj): 133 reftype = type_obj.i_type_spec.i_target_node.search_one('type') 134 if is_leafref(reftype): 135 return dig_leafref(reftype) 136 else: 137 return reftype 138 139 140 def emit_class_def(ctx, stmt, struct_name, prefix, fd): 141 if len(stmt.i_children) == 1 and is_list(stmt.i_children[0]): 142 return 143 144 print('// struct for container %s:%s.' % (prefix, stmt.arg), file=fd) 145 emit_description(stmt, fd) 146 print('type %s struct {' % convert_to_golang(struct_name), file=fd) 147 148 equal_elems = [] 149 150 for child in stmt.i_children: 151 152 if child.path in _path_exclude: 153 continue 154 155 container_or_list_name = child.uniq_name 156 val_name_go = convert_to_golang(child.arg) 157 child_prefix = get_orig_prefix(child.i_orig_module) 158 tag_name = child.uniq_name.lower() 159 equal_type = EQUAL_TYPE_LEAF 160 equal_data = None 161 print('// original -> %s:%s' % (child_prefix, container_or_list_name), file=fd) 162 163 # case leaf 164 if is_leaf(child): 165 type_obj = child.search_one('type') 166 type_name = type_obj.arg 167 168 # case identityref 169 if is_identityref(type_obj): 170 emit_type_name = convert_to_golang(type_obj.search_one('base').arg.split(':')[-1]) 171 172 # case leafref 173 elif is_leafref(type_obj): 174 if type_obj.search_one('path').arg.startswith('../config'): 175 continue 176 t = dig_leafref(type_obj) 177 if is_translation_required(t): 178 print('// %s:%s\'s original type is %s.' % (child_prefix, container_or_list_name, t.arg), file=fd) 179 emit_type_name = translate_type(t.arg) 180 elif is_identityref(t): 181 emit_type_name = convert_to_golang(t.search_one('base').arg.split(':')[-1]) 182 else: 183 emit_type_name = t.arg 184 185 # case embeded enumeration 186 elif is_enum(type_obj): 187 emit_type_name = val_name_go 188 189 # case translation required 190 elif is_translation_required(type_obj): 191 print('// %s:%s\'s original type is %s.' % (child_prefix, container_or_list_name, type_name), file=fd) 192 emit_type_name = translate_type(type_name) 193 194 # case other primitives 195 elif is_builtin_type(type_obj): 196 emit_type_name = type_name 197 198 # default 199 else: 200 base_module = type_obj.i_orig_module.i_prefix 201 t = lookup_typedef(ctx, base_module, type_name) 202 # print(t.golang_name, file=sys.stderr) 203 emit_type_name = t.golang_name 204 205 # case 'case' 206 if is_case(child): 207 continue 208 209 if is_choice(child) and is_enum_choice(child): 210 emit_type_name = val_name_go 211 212 # case leaflist 213 if is_leaflist(child): 214 type_obj = child.search_one('type') 215 type_name = type_obj.arg 216 val_name_go = val_name_go + 'List' 217 tag_name += '-list' 218 equal_type = EQUAL_TYPE_ARRAY 219 220 # case leafref 221 if is_leafref(type_obj): 222 t = dig_leafref(type_obj) 223 emit_type_name = '[]' + t.arg 224 225 # case identityref 226 elif is_identityref(type_obj): 227 emit_type_name = '[]' + convert_to_golang(type_obj.search_one('base').arg.split(':')[-1]) 228 229 # case translation required 230 elif is_translation_required(type_obj): 231 print('// original type is list of %s' % type_obj.arg, file=fd) 232 emit_type_name = '[]' + translate_type(type_name) 233 234 # case other primitives 235 elif is_builtin_type(type_obj): 236 emit_type_name = '[]' + type_name 237 238 # default 239 else: 240 base_module = type_obj.i_orig_module.i_prefix 241 t = lookup_typedef(ctx, base_module, type_name) 242 emit_type_name = '[]' + t.golang_name 243 244 # case container 245 elif is_container(child) or (is_choice(child) and not is_enum_choice(child)): 246 key = child_prefix + ':' + container_or_list_name 247 t = ctx.golang_struct_names[key] 248 val_name_go = t.golang_name 249 if len(t.i_children) == 1 and is_list(t.i_children[0]): 250 c = t.i_children[0] 251 emit_type_name = '[]' + c.golang_name 252 equal_type = EQUAL_TYPE_MAP 253 equal_data = c.search_one('key').arg 254 leaf = c.search_one('leaf').search_one('type') 255 if leaf.arg == 'leafref' and leaf.search_one('path').arg.startswith('../config'): 256 equal_data = 'config.' + equal_data 257 else: 258 emit_type_name = t.golang_name 259 equal_type = EQUAL_TYPE_CONTAINER 260 261 # case list 262 elif is_list(child): 263 key = child_prefix + ':' + container_or_list_name 264 t = ctx.golang_struct_names[key] 265 val_name_go = val_name_go + 'List' 266 tag_name += '-list' 267 emit_type_name = '[]' + t.golang_name 268 equal_type = EQUAL_TYPE_MAP 269 equal_data = child.search_one('key').arg 270 271 if is_container(child): 272 name = emit_type_name 273 if name.startswith(convert_to_golang(struct_name)) and name.endswith("Config"): 274 tag_name = 'config' 275 val_name_go = 'Config' 276 elif name.startswith(convert_to_golang(struct_name)) and name.endswith("State"): 277 tag_name = 'state' 278 val_name_go = 'State' 279 280 emit_description(child, fd=fd) 281 print(' {0}\t{1} `mapstructure:"{2}" json:"{2},omitempty"`'.format(val_name_go, emit_type_name, tag_name), file=fd) 282 283 equal_elems.append((val_name_go, emit_type_name, equal_type, equal_data)) 284 285 print('}', file=fd) 286 287 if not struct_name.endswith('state'): 288 print('func (lhs *{0}) Equal(rhs *{0}) bool {{'.format(convert_to_golang(struct_name)), file=fd) 289 print('if lhs == nil || rhs == nil {', file=fd) 290 print('return false', file=fd) 291 print('}', file=fd) 292 293 for val_name, type_name, typ, elem in equal_elems: 294 if val_name == 'State': 295 continue 296 if typ == EQUAL_TYPE_LEAF: 297 if type_name == '[]byte': 298 print('if bytes.Compare(lhs.{0}, rhs.{0}) != 0 {{'.format(val_name), file=fd) 299 else: 300 print('if lhs.{0} != rhs.{0} {{'.format(val_name), file=fd) 301 print('return false', file=fd) 302 print('}', file=fd) 303 elif typ == EQUAL_TYPE_CONTAINER: 304 print('if !lhs.{0}.Equal(&(rhs.{0})) {{'.format(val_name), file=fd) 305 print('return false', file=fd) 306 print('}', file=fd) 307 elif typ == EQUAL_TYPE_ARRAY: 308 print('if len(lhs.{0}) != len(rhs.{0}) {{'.format(val_name), file=fd) 309 print('return false', file=fd) 310 print('}', file=fd) 311 print('for idx, l := range lhs.{0} {{'.format(val_name), file=fd) 312 if type_name == '[][]byte': 313 print('if bytes.Compare(l, rhs.{0}[idx]) != 0 {{'.format(val_name), file=fd) 314 else: 315 print('if l != rhs.{0}[idx] {{'.format(val_name), file=fd) 316 print('return false', file=fd) 317 print('}', file=fd) 318 print('}', file=fd) 319 elif typ == EQUAL_TYPE_MAP: 320 print('if len(lhs.{0}) != len(rhs.{0}) {{'.format(val_name), file=fd) 321 print('return false', file=fd) 322 print('}', file=fd) 323 print('{', file=fd) 324 print('lmap := make(map[string]*{0})'.format(type_name[2:]), file=fd) 325 print('for i, l := range lhs.{0} {{'.format(val_name), file=fd) 326 print('lmap[mapkey(i, string({0}))] = &lhs.{1}[i]'.format(' + '.join('l.{0}'.format(convert_to_golang(v)) for v in elem.split(' ')), val_name), file=fd) 327 print('}', file=fd) 328 print('for i, r := range rhs.{0} {{'.format(val_name), file=fd) 329 print('if l, y := lmap[mapkey(i, string({0}))]; !y {{'.format('+'.join('r.{0}'.format(convert_to_golang(v)) for v in elem.split(' '))), file=fd) 330 print('return false', file=fd) 331 print('} else if !r.Equal(l) {', file=fd) 332 print('return false', file=fd) 333 print('}', file=fd) 334 print('}', file=fd) 335 print('}', file=fd) 336 else: 337 sys.stderr.write("invalid equal type %s", typ) 338 339 print('return true', file=fd) 340 print('}', file=fd) 341 342 343 def get_orig_prefix(mod): 344 orig = mod.i_orig_module 345 if orig: 346 get_orig_prefix(orig) 347 else: 348 return mod.i_prefix 349 350 351 def get_path(c): 352 path = '' 353 if c.parent is not None: 354 p = '' 355 if hasattr(c, 'i_module'): 356 mod = c.i_module 357 prefix = mod.search_one('prefix') 358 if prefix: 359 p = prefix.arg + ":" 360 361 path = get_path(c.parent) + "/" + p + c.arg 362 return path 363 364 365 # define container embedded enums 366 def define_enum(ctx, mod, c): 367 prefix = mod.i_prefix 368 c.path = get_path(c) 369 c.golang_name = convert_to_golang(c.arg) 370 if prefix in ctx.golang_typedef_map: 371 ctx.golang_typedef_map[prefix][c.arg] = c 372 else: 373 ctx.golang_typedef_map[prefix] = {c.arg: c} 374 375 376 def visit_children(ctx, mod, children): 377 for c in children: 378 if is_case(c): 379 prefix = get_orig_prefix(c.parent.i_orig_module) 380 c.i_orig_module = c.parent.i_orig_module 381 else: 382 prefix = get_orig_prefix(c.i_orig_module) 383 384 c.uniq_name = c.arg 385 if c.arg == 'config': 386 c.uniq_name = c.parent.uniq_name + '-config' 387 388 elif c.arg == 'state': 389 c.uniq_name = c.parent.uniq_name + '-state' 390 391 elif c.arg == 'graceful-restart' and prefix == 'bgp-mp': 392 c.uniq_name = 'mp-graceful-restart' 393 394 if is_leaf(c) and is_enum(c.search_one('type')): 395 define_enum(ctx, mod, c) 396 397 elif is_list(c) or is_container(c) or is_choice(c): 398 c.golang_name = convert_to_golang(c.uniq_name) 399 400 if is_choice(c): 401 picks = pickup_choice(c) 402 c.i_children = picks 403 if is_enum_choice(c): 404 define_enum(ctx, mod, c) 405 continue 406 407 prefix_name = prefix + ':' + c.uniq_name 408 if prefix_name in ctx.golang_struct_names: 409 ext_c = ctx.golang_struct_names.get(prefix_name) 410 ext_c_child_count = len(getattr(ext_c, "i_children")) 411 current_c_child_count = len(getattr(c, "i_children")) 412 if ext_c_child_count < current_c_child_count: 413 c.module_prefix = prefix 414 ctx.golang_struct_names[prefix_name] = c 415 idx = ctx.golang_struct_def.index(ext_c) 416 ctx.golang_struct_def[idx] = c 417 else: 418 c.module_prefix = prefix 419 ctx.golang_struct_names[prefix_name] = c 420 ctx.golang_struct_def.append(c) 421 422 c.path = get_path(c) 423 # print(c.path, file=sys.stderr) 424 if hasattr(c, 'i_children'): 425 visit_children(ctx, mod, c.i_children) 426 427 428 def pickup_choice(c): 429 element = [] 430 for child in c.i_children: 431 if is_case(child): 432 element = element + child.i_children 433 434 return element 435 436 437 def get_type_spec(stmt): 438 for s in stmt.substmts: 439 if hasattr(s, 'i_type_spec'): 440 return s.i_type_spec.name 441 442 return None 443 444 445 def visit_typedef(ctx, mod): 446 prefix = mod.i_prefix 447 child_map = {} 448 for stmt in mod.substmts: 449 if is_typedef(stmt): 450 stmt.path = get_path(stmt) 451 # print('stmt.path = "%s"' % stmt.path, file=sys.stderr) 452 name = stmt.arg 453 stmt.golang_name = convert_to_golang(name) 454 # print('stmt.golang_name = "%s"' % stmt.golang_name, file=sys.stderr) 455 child_map[name] = stmt 456 457 ctx.golang_typedef_map[prefix] = child_map 458 # print('ctx.golang_typedef_map["%s"] = %s' % (prefix, child_map), file=sys.stderr) 459 prefix_rel = ctx.prefix_rel[prefix] 460 ctx.golang_typedef_map[prefix_rel] = child_map 461 # print('ctx.golang_typedef_map["%s"] = %s' % (prefix_rel, child_map)), file=sys.stderr) 462 463 464 def visit_identity(ctx, mod): 465 prefix = mod.i_prefix 466 child_map = {} 467 for stmt in mod.substmts: 468 if is_identity(stmt): 469 name = stmt.arg 470 stmt.golang_name = convert_to_golang(name) 471 # print('stmt.golang_name = "%s"' % stmt.golang_name, file=sys.stderr) 472 child_map[name] = stmt 473 474 base = stmt.search_one('base') 475 if base: 476 base_name = base.arg 477 if ':' in base_name: 478 base_prefix, base_name = base_name.split(':', 1) 479 if base_prefix in ctx.golang_identity_map: 480 ctx.golang_identity_map[base_prefix][base_name].substmts.append(stmt) 481 else: 482 child_map[base_name].substmts.append(stmt) 483 484 ctx.golang_identity_map[prefix] = child_map 485 # print('ctx.golang_identity_map["%s"] = %s\n' % (prefix, child_map), file=sys.stderr) 486 prefix_rel = ctx.prefix_rel[prefix] 487 ctx.golang_identity_map[prefix_rel] = child_map 488 # print('ctx.golang_identity_map["%s"] = %s\n' % (prefix_rel, child_map), file=sys.stderr) 489 490 491 def lookup_identity(ctx, default_prefix, identity_name): 492 result = lookup(ctx.golang_identity_map, default_prefix, identity_name) 493 return result 494 495 496 def lookup_typedef(ctx, default_prefix, type_name): 497 result = lookup(ctx.golang_typedef_map, default_prefix, type_name) 498 return result 499 500 501 def lookup(basemap, default_prefix, key): 502 if ':' in key: 503 pref, name = key.split(':') 504 else: 505 pref = default_prefix 506 name = key 507 508 if pref in basemap: 509 return basemap[pref].get(name, None) 510 else: 511 return key 512 513 514 def emit_description(stmt, fd): 515 desc = stmt.search_one('description') 516 if desc is None: 517 return None 518 desc_words = desc.arg if desc.arg.endswith('.') else desc.arg + '.' 519 print('// %s' % desc_words.replace('\n', '\n// '), file=fd) 520 521 522 def emit_enum(prefix, name, stmt, substmts, fd): 523 type_name_org = name 524 type_name = stmt.golang_name 525 print('// typedef for identity %s:%s.' % (prefix, type_name_org), file=fd) 526 emit_description(stmt, fd) 527 print('type %s string' % type_name, file=fd) 528 529 const_prefix = convert_const_prefix(type_name_org) 530 print('const (', file=fd) 531 m = {} 532 533 if is_choice(stmt) and is_enum_choice(stmt): 534 n = namedtuple('Statement', ['arg']) 535 n.arg = 'none' 536 substmts = [n] + substmts 537 538 for sub in substmts: 539 enum_name = '%s_%s' % (const_prefix, convert_const_prefix(sub.arg)) 540 m[sub.arg.lower()] = enum_name 541 print(' %s %s = "%s"' % (enum_name, type_name, sub.arg.lower()), file=fd) 542 print(')\n', file=fd) 543 544 print('var %sToIntMap = map[%s]int {' % (type_name, type_name), file=fd) 545 for i, sub in enumerate(substmts): 546 enum_name = '%s_%s' % (const_prefix, convert_const_prefix(sub.arg)) 547 print(' %s: %d,' % (enum_name, i), file=fd) 548 print('}\n', file=fd) 549 550 print('var IntTo%sMap = map[int]%s {' % (type_name, type_name), file=fd) 551 for i, sub in enumerate(substmts): 552 enum_name = '%s_%s' % (const_prefix, convert_const_prefix(sub.arg)) 553 print(' %d: %s,' % (i, enum_name), file=fd) 554 print('}\n', file=fd) 555 556 print('func (v %s) Validate() error {' % type_name, file=fd) 557 print('if _, ok := %sToIntMap[v]; !ok {' % type_name, file=fd) 558 print('return fmt.Errorf("invalid %s: %%s", v)' % type_name, file=fd) 559 print('}', file=fd) 560 print('return nil', file=fd) 561 print('}\n', file=fd) 562 563 if stmt.search_one('default'): 564 default = stmt.search_one('default') 565 print('func (v %s) Default() %s {' % (type_name, type_name), file=fd) 566 print('return %s' % m[default.arg.lower()], file=fd) 567 print('}\n', file=fd) 568 569 print('func (v %s) DefaultAsNeeded() %s {' % (type_name, type_name), file=fd) 570 print(' if string(v) == "" {', file=fd) 571 print(' return v.Default()', file=fd) 572 print('}', file=fd) 573 print(' return v', file=fd) 574 print('}', file=fd) 575 576 print('func (v %s) ToInt() int {' % type_name, file=fd) 577 print('_v := v.DefaultAsNeeded()') 578 print('i, ok := %sToIntMap[_v]' % type_name, file=fd) 579 580 else: 581 print('func (v %s) ToInt() int {' % type_name, file=fd) 582 print('i, ok := %sToIntMap[v]' % type_name, file=fd) 583 print('if !ok {', file=fd) 584 print('return -1', file=fd) 585 print('}', file=fd) 586 print('return i', file=fd) 587 print('}', file=fd) 588 589 590 def emit_typedef(ctx, mod, fd): 591 prefix = mod.i_prefix 592 t_map = ctx.golang_typedef_map[prefix] 593 for name, stmt in t_map.items(): 594 if stmt.path in _typedef_exclude: 595 continue 596 597 # skip identityref type because currently skip identity 598 if get_type_spec(stmt) == 'identityref': 599 continue 600 601 type_name_org = name 602 type_name = stmt.golang_name 603 if type_name in ctx.emitted_type_names: 604 print("warning %s: %s has already been emitted from %s." 605 % (prefix + ":" + type_name_org, type_name_org, ctx.emitted_type_names[type_name]), 606 file=sys.stderr) 607 continue 608 609 ctx.emitted_type_names[type_name] = prefix + ":" + type_name_org 610 611 t = stmt.search_one('type') 612 if not t and is_choice(stmt): 613 emit_enum(prefix, type_name_org, stmt, stmt.i_children, fd) 614 elif is_enum(t): 615 emit_enum(prefix, type_name_org, stmt, t.substmts, fd) 616 elif is_union(t): 617 print('// typedef for typedef %s:%s.' % (prefix, type_name_org), file=fd) 618 emit_description(t, fd) 619 print('type %s string' % type_name, file=fd) 620 else: 621 if is_leafref(t): 622 t = dig_leafref(t) 623 624 print('// typedef for typedef %s:%s.' % (prefix, type_name_org), file=fd) 625 if is_builtin_type(t): 626 emit_description(t, fd) 627 print('type %s %s' % (type_name, t.arg), file=fd) 628 elif is_translation_required(t): 629 print('// %s:%s\'s original type is %s.' % (prefix, name, t.arg), file=fd) 630 emit_description(t, fd) 631 print('type %s %s' % (type_name, translate_type(t.arg)), file=fd) 632 else: 633 m = ctx.golang_typedef_map 634 for k in t.arg.split(':'): 635 m = m[k] 636 emit_description(t, fd) 637 print('type %s %s' % (type_name, m.golang_name), file=fd) 638 639 640 def emit_identity(ctx, mod, fd): 641 prefix = mod.i_prefix 642 i_map = ctx.golang_identity_map[prefix] 643 for name, stmt in i_map.items(): 644 enums = stmt.search('identity') 645 if len(enums) > 0: 646 emit_enum(prefix, name, stmt, enums, fd) 647 648 649 def is_reference(s): 650 return s.arg in ['leafref', 'identityref'] 651 652 653 def is_leafref(s): 654 return s.arg in ['leafref'] 655 656 657 def is_identityref(s): 658 return s.arg in ['identityref'] 659 660 661 def is_enum(s): 662 return s.arg in ['enumeration'] 663 664 665 def is_union(s): 666 return s.arg in ['union'] 667 668 669 def is_typedef(s): 670 return s.keyword in ['typedef'] 671 672 673 def is_identity(s): 674 return s.keyword in ['identity'] 675 676 677 def is_leaf(s): 678 return s.keyword in ['leaf'] 679 680 681 def is_leaflist(s): 682 return s.keyword in ['leaf-list'] 683 684 685 def is_list(s): 686 return s.keyword in ['list'] 687 688 689 def is_container(s): 690 return s.keyword in ['container'] 691 692 693 def is_case(s): 694 return s.keyword in ['case'] 695 696 697 def is_choice(s): 698 return s.keyword in ['choice'] 699 700 701 def is_enum_choice(s): 702 return all(e.search_one('type').arg in _type_enum_case for e in s.i_children) 703 704 705 _type_enum_case = [ 706 'empty', 707 ] 708 709 710 def is_builtin_type(t): 711 return t.arg in _type_builtin 712 713 714 def is_translation_required(t): 715 return t.arg in list(_type_translation_map.keys()) 716 717 718 _type_translation_map = { 719 'union': 'string', 720 'decimal64': 'float64', 721 'boolean': 'bool', 722 'empty': 'bool', 723 'inet:ip-address': 'string', 724 'inet:ip-prefix': 'string', 725 'inet:ipv4-address': 'string', 726 'inet:as-number': 'uint32', 727 'bgp-set-community-option-type': 'string', 728 'inet:port-number': 'uint16', 729 'yang:timeticks': 'int64', 730 'ptypes:install-protocol-type': 'string', 731 'binary': '[]byte', 732 'route-family': 'bgp.RouteFamily', 733 'bgp-capability': 'bgp.ParameterCapabilityInterface', 734 'bgp-open-message': '*bgp.BGPMessage', 735 } 736 737 738 _type_builtin = [ 739 "union", 740 "int8", 741 "int16", 742 "int32", 743 "int64", 744 "string", 745 "uint8", 746 "uint16", 747 "uint32", 748 "uint64", 749 ] 750 751 752 _module_excluded = [ 753 "ietf-inet-types", 754 "ietf-yang-types", 755 ] 756 757 _path_exclude = [ 758 "/rpol:routing-policy/rpol:defined-sets/rpol:neighbor-sets/rpol:neighbor-set/rpol:neighbor", 759 "/rpol:routing-policy/rpol:defined-sets/bgp-pol:bgp-defined-sets/bgp-pol:community-sets/bgp-pol:community-set/bgp-pol:community-member", 760 "/rpol:routing-policy/rpol:defined-sets/bgp-pol:bgp-defined-sets/bgp-pol:ext-community-sets/bgp-pol:ext-community-set/bgp-pol:ext-community-member", 761 "/rpol:routing-policy/rpol:defined-sets/bgp-pol:bgp-defined-sets/bgp-pol:as-path-sets/bgp-pol:as-path-set/bgp-pol:as-path-set-member", 762 ] 763 764 _typedef_exclude = [ 765 "/gobgp:bgp-capability", 766 "/gobgp:bgp-open-message", 767 ] 768 769 770 def generate_header(fd): 771 print(_COPYRIGHT_NOTICE, file=fd) 772 print('package oc', file=fd) 773 print('', file=fd) 774 print('import (', file=fd) 775 print('"fmt"', file=fd) 776 print('', file=fd) 777 print('"github.com/osrg/gobgp/v3/pkg/packet/bgp"', file=fd) 778 print(')', file=fd) 779 print('', file=fd) 780 781 782 def generate_common_functions(fd): 783 print('func mapkey(index int, name string) string {', file=fd) 784 print('if name != "" {', file=fd) 785 print('return name', file=fd) 786 print('}', file=fd) 787 print('return fmt.Sprintf("%v", index)', file=fd) 788 print('}', file=fd) 789 790 791 def translate_type(key): 792 if key in _type_translation_map.keys(): 793 return _type_translation_map[key] 794 else: 795 return key 796 797 798 # 'hoge-hoge' -> 'HogeHoge' 799 def convert_to_golang(type_string): 800 a = type_string.split('.') 801 return '.'.join(''.join(t.capitalize() for t in x.split('-')) for x in a) 802 803 804 # 'hoge-hoge' -> 'HOGE_HOGE' 805 def convert_const_prefix(type_string): 806 return type_string.replace('-', '_').upper() 807 808 809 def chop_suf(s, suf): 810 if not s.endswith(suf): 811 return s 812 return s[:-len(suf)]