// FormatNode writes e, formatted almost like a protobuf message, to w. func FormatNode(w io.Writer, e *yang.Entry) { fmt.Fprintln(w) if e.Description != "" { fmt.Fprintln(indent.NewWriter(w, "// "), e.Description) } fmt.Fprintf(w, "message %s {\n", fixName(e.Name)) var names []string for k := range e.Dir { names = append(names, k) } sort.Strings(names) for x, k := range names { se := e.Dir[k] if se.Description != "" { fmt.Fprintln(indent.NewWriter(w, " // "), se.Description) } if se.IsList { fmt.Fprint(w, " repeated ") } else { fmt.Fprint(w, " optional ") } if len(se.Dir) == 0 && se.Type != nil { // TODO(borman): this is probably an empty container. kind := "UNKNOWN TYPE" if se.Type != nil { kind = kind2proto[se.Type.Kind] } fmt.Fprintf(w, "%s %s = %d; // %s\n", kind, fixName(k), x+1, yang.Source(se.Node)) continue } fmt.Fprintf(w, "%s %s = %d; // %s\n", fixName(se.Name), fixName(k), x+1, yang.Source(se.Node)) } // { to match the brace below to keep brace matching working fmt.Fprintln(w, "}") }
// printType prints type t in a moderately human readable format to w. func printType(w io.Writer, t *yang.YangType, verbose bool) { if verbose && t.Base != nil { base := yang.Source(t.Base) if base == "unknown" { base = "unnamed type" } fmt.Fprintf(w, "%s: ", base) } fmt.Fprintf(w, "%s", t.Root.Name) if t.Kind.String() != t.Root.Name { fmt.Fprintf(w, "(%s)", t.Kind) } if t.Units != "" { fmt.Fprintf(w, " units=%s", t.Units) } if t.Default != "" { fmt.Fprintf(w, " default=%q", t.Default) } if t.FractionDigits != 0 { fmt.Fprintf(w, " fraction-digits=%d", t.FractionDigits) } if len(t.Length) > 0 { fmt.Fprintf(w, " length=%s", t.Length) } if t.Kind == yang.YinstanceIdentifier && !t.OptionalInstance { fmt.Fprintf(w, " required") } if t.Kind == yang.Yleafref && t.Path != "" { fmt.Fprintf(w, " path=%q", t.Path) } if len(t.Pattern) > 0 { fmt.Fprintf(w, " pattern=%s", strings.Join(t.Pattern, "|")) } b := yang.BaseTypedefs[t.Kind.String()].YangType if len(t.Range) > 0 && !t.Range.Equal(b.Range) { fmt.Fprintf(w, " range=%s", t.Range) } if len(t.Type) > 0 { fmt.Fprintf(w, "union{\n") for _, t := range t.Type { printType(indent.NewWriter(w, " "), t, verbose) } fmt.Fprintf(w, "}") } fmt.Fprintf(w, ";\n") }
// YTPrint prints type t in a moderately human readable format to w. func YTPrint(w io.Writer, t *yang.YangType) { if t.Base != nil { fmt.Fprintf(w, "%s: ", yang.Source(t.Base)) } fmt.Fprintf(w, "%s", t.Root.Name) if t.Kind.String() != t.Root.Name { fmt.Fprintf(w, "(%s)", t.Kind) } if t.Units != "" { fmt.Fprintf(w, " units=%s", t.Units) } if t.Default != "" { fmt.Fprintf(w, " default=%q", t.Default) } if t.FractionDigits != 0 { fmt.Fprintf(w, " fraction-digits=%d", t.FractionDigits) } if len(t.Length) > 0 { fmt.Fprintf(w, " length=%s", t.Length) } if t.Kind == yang.YinstanceIdentifier && !t.OptionalInstance { fmt.Fprintf(w, " required") } if t.Kind == yang.Yleafref && t.Path != "" { fmt.Fprintf(w, " path=%q", t.Path) } if len(t.Pattern) > 0 { fmt.Fprintf(w, " pattern=%s", strings.Join(t.Pattern, "|")) } if len(t.Type) > 0 { fmt.Fprintf(w, " union...") } b := yang.BaseTypedefs[t.Kind.String()].YangType if len(t.Range) > 0 && !t.Range.Equal(b.Range) { fmt.Fprintf(w, " range=%s", t.Range) } fmt.Fprintf(w, ";\n") }
// FormatNode writes e, formatted almost like a protobuf message, to w. func FormatNode(w io.Writer, e *yang.Entry) { var names []string for k, se := range e.Dir { if se.RPC != nil { names = append(names, k) } } needEmpty := false if len(names) > 0 { sort.Strings(names) fmt.Fprintf(w, "service %s {\n", fixName(e.Name)) for _, k := range names { rpc := e.Dir[k].RPC k = fixName(k) iName := "Empty" oName := "Empty" if rpc.Input != nil { iName = k + "Request" rpc.Input.Name = iName if isStream(rpc.Input) { iName = "stream " + iName } } if rpc.Output != nil { oName = k + "Response" rpc.Output.Name = oName if isStream(rpc.Output) { oName = "stream " + oName } } needEmpty = needEmpty || rpc.Input == nil || rpc.Output == nil fmt.Fprintf(w, " rpc %s (%s) returns (%s);\n", k, iName, oName) } fmt.Fprintln(w, "}") for _, k := range names { rpc := e.Dir[k].RPC if rpc.Input != nil { FormatNode(w, rpc.Input) } if rpc.Output != nil { FormatNode(w, rpc.Output) } } } if needEmpty { fmt.Fprintln(w, "\nmessage Empty { }") } names = nil for k, se := range e.Dir { if se.RPC == nil { names = append(names, k) } } if len(names) == 0 { return } fmt.Fprintln(w) if e.Description != "" { fmt.Fprintln(indent.NewWriter(w, "// "), e.Description) } fmt.Fprintf(w, "message %s {\n", fixName(e.Name)) sort.Strings(names) for x, k := range names { se := e.Dir[k] if se.Description != "" { fmt.Fprintln(indent.NewWriter(w, " // "), se.Description) } if se.ListAttr != nil { fmt.Fprint(w, " repeated ") } else { fmt.Fprint(w, " optional ") } if len(se.Dir) == 0 && se.Type != nil { // TODO(borman): this is probably an empty container. kind := "UNKNOWN TYPE" if se.Type != nil { kind = kind2proto[se.Type.Kind] } fmt.Fprintf(w, "%s %s = %d; // %s\n", kind, fixName(k), x+1, yang.Source(se.Node)) continue } fmt.Fprintf(w, "%s %s = %d; // %s\n", fixName(se.Name), fixName(k), x+1, yang.Source(se.Node)) } // { to match the brace below to keep brace matching working fmt.Fprintln(w, "}") }
// printNode writes e, formatted almost like a protobuf message, to w. func (pf *protofile) printNode(w io.Writer, e *yang.Entry, nest bool) { nodes := children(e) if !protoNoComments && e.Description != "" { fmt.Fprintln(indent.NewWriter(w, "// "), e.Description) } messageName := pf.fullName(e) mi := pf.messages[messageName] if mi == nil { mi = &messageInfo{ fields: map[string]int{}, } pf.messages[messageName] = mi } fmt.Fprintf(w, "message %s {", pf.messageName(e)) // matching brace } if protoWithSource { fmt.Fprintf(w, " // %s", yang.Source(e.Node)) } fmt.Fprintln(w) for i, se := range nodes { k := se.Name if !protoNoComments && se.Description != "" { fmt.Fprintln(indent.NewWriter(w, " // "), se.Description) } if nest && (len(se.Dir) > 0 || se.Type == nil) { pf.printNode(indent.NewWriter(w, " "), se, true) } prefix := " " if se.ListAttr != nil { prefix = " repeated " } else if proto2 { prefix = " optional " } name := pf.fieldName(k) printed := false var kind string if len(se.Dir) > 0 || se.Type == nil { kind = pf.messageName(se) } else if se.Type.Kind == yang.Ybits { values := dedup(se.Type.Bit.Values()) asComment := false switch { case len(values) > 0 && values[len(values)-1] > 63: if i != 0 { fmt.Fprintln(w) } fmt.Fprintf(w, " // *WARNING* bitfield %s has more than 64 positions\n", name) kind = "uint64" asComment = true case len(values) > 0 && values[len(values)-1] > 31: if i != 0 { fmt.Fprintln(w) } fmt.Fprintf(w, " // bitfield %s to large for enum\n", name) kind = "uint64" asComment = true default: kind = pf.fixName(se.Name) } if !asComment { fmt.Fprintf(w, " enum %s {\n", kind) fmt.Fprintf(w, " %s_FIELD_NOT_SET = 0;\n", kind) } else { fmt.Fprintf(w, " // Values:\n") } names := map[int64][]string{} for n, v := range se.Type.Bit.NameMap() { names[v] = append(names[v], n) } for _, v := range values { ns := names[v] sort.Strings(ns) if asComment { for _, n := range ns { fmt.Fprintf(w, " // %s = 1 << %d\n", n, v) } } else { n := strings.ToUpper(pf.fieldName(ns[0])) fmt.Fprintf(w, " %s_%s = %d;\n", kind, n, 1<<uint(v)) for _, n := range ns[1:] { n = strings.ToUpper(pf.fieldName(n)) fmt.Fprintf(w, " // %s = %d; (DUPLICATE VALUE)\n", n, 1<<uint(v)) } } } if !asComment { fmt.Fprintf(w, " };\n") } } else if se.Type.Kind == yang.Ydecimal64 { kind = "Decimal64" pf.hasDecimal64 = true } else if se.Type.Kind == yang.Yenum { kind = pf.fixName(se.Name) fmt.Fprintf(w, " enum %s {", kind) if protoWithSource { fmt.Fprintf(w, " // %s", yang.Source(se.Node)) } fmt.Fprintln(w) for i, n := range se.Type.Enum.Names() { fmt.Fprintf(w, " %s_%s = %d;\n", kind, strings.ToUpper(pf.fieldName(n)), i) } fmt.Fprintf(w, " };\n") } else if se.Type.Kind == yang.Yunion { types := pf.unionTypes(se.Type, map[string]bool{}) switch len(types) { case 0: fmt.Fprintf(w, " // *WARNING* union %s has no types\n", se.Name) printed = true case 1: kind = types[0] default: iw := w kind = pf.fixName(se.Name) if se.ListAttr != nil { fmt.Fprintf(w, " message %s {\n", kind) iw = indent.NewWriter(w, " ") } fmt.Fprintf(iw, " oneof %s {", kind) // matching brace } if protoWithSource { fmt.Fprintf(w, " // %s", yang.Source(se.Node)) } fmt.Fprintln(w) for _, tkind := range types { fmt.Fprintf(iw, " %s %s_%s = %d;\n", tkind, kind, tkind, mi.tag(name, tkind, false)) } // { to match the brace below to keep brace matching working fmt.Fprintf(iw, " }\n") if se.ListAttr != nil { fmt.Fprintf(w, " }\n") } else { printed = true } } } else { kind = kind2proto[se.Type.Kind] } if !printed { fmt.Fprintf(w, "%s%s %s = %d;", prefix, kind, name, mi.tag(name, kind, se.ListAttr != nil)) if protoWithSource { fmt.Fprintf(w, " // %s", yang.Source(se.Node)) } fmt.Fprintln(w) } } // { to match the brace below to keep brace matching working fmt.Fprintln(w, "}") }