Skip to content

Commit

Permalink
generate: minor cleanup && support flexible non-top-level stuff
Browse files Browse the repository at this point in the history
This makes non-top-level structs that have WithVersionField true more
unified with the top level encoders, and then adds an easier to reason
about regular expression to parse non-top-level structs. The regex now
parses flexible versions, which will be useful for the next commit.

This does shuffle around some field definitions in the encoding, but
that's small.
  • Loading branch information
twmb committed Nov 10, 2020
1 parent 800ba9e commit 724a2c1
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 14 deletions.
13 changes: 7 additions & 6 deletions generate/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,6 @@ func (s Struct) WriteDecode(l *LineWriter) {
die("expected field version type to be int16, was %v", f.Type)
}
rangeFrom = s.Fields[1:]
l.Write("version := b.Int16()")
l.Write("v.Version = version")
}
l.Write("s := v")

Expand Down Expand Up @@ -625,7 +623,7 @@ func (s Struct) WriteAppendFunc(l *LineWriter) {
l.Write("version := v.Version")
l.Write("_ = version")
}
if s.TopLevel && s.FlexibleAt >= 0 {
if s.FlexibleAt >= 0 {
l.Write("isFlexible := version >= %d", s.FlexibleAt)
l.Write("_ = isFlexible")
}
Expand All @@ -637,15 +635,18 @@ func (s Struct) WriteAppendFunc(l *LineWriter) {
func (s Struct) WriteDecodeFunc(l *LineWriter) {
l.Write("func (v *%s) ReadFrom(src []byte) error {", s.Name)
l.Write("v.Default()")
if s.TopLevel {
l.Write("b := kbin.Reader{Src: src}")
if s.WithVersionField {
l.Write("v.Version = b.Int16()")
}
if s.TopLevel || s.WithVersionField {
l.Write("version := v.Version")
l.Write("_ = version")
}
if s.TopLevel && s.FlexibleAt >= 0 {
if s.FlexibleAt >= 0 {
l.Write("isFlexible := version >= %d", s.FlexibleAt)
l.Write("_ = isFlexible")
}
l.Write("b := kbin.Reader{Src: src}")
s.WriteDecode(l)
l.Write("return b.Complete()")
l.Write("}")
Expand Down
3 changes: 3 additions & 0 deletions generate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,9 @@ func main() {
} else if !s.Anonymous && !s.WithNoEncoding {
s.WriteAppendFunc(l)
s.WriteDecodeFunc(l)
if s.FromFlexible {
s.WriteIsFlexibleFunc(l)
}
}

// everything gets a default and new function
Expand Down
44 changes: 36 additions & 8 deletions generate/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,13 @@ func parseFieldLength(in string) (string, int, error) {
return lr[0], length, nil
}

// 0: entire thing
// 1: name
// 2: "no encoding" if present
// 3: "with (encoded )? version field" if present
// 5: flexible version, if 2 is present
var notTopLevelRe = regexp.MustCompile(`^([A-Za-z0-9]+) => not top level(?:, (?:(no encoding)|(with version field)(?:, flexible v(\d+)\+)?))?$`)

// Parse parses the raw contents of a messages file and adds all newly
// parsed structs to newStructs.
func Parse(raw []byte) {
Expand Down Expand Up @@ -360,14 +367,30 @@ func Parse(raw []byte) {
topLevel := true
withVersionField, withNoEncoding := false, false

name := strings.TrimSuffix(line, " => not top level")
if withVersion := strings.TrimSuffix(name, " => not top level, with version field"); withVersion != name {
name = withVersion
withVersionField = true
}
if noEncoding := strings.TrimSuffix(name, " => not top level, no encoding"); noEncoding != name {
name = noEncoding
flexibleAt := -1
fromFlexible := false

nameMatch := notTopLevelRe.FindStringSubmatch(line)

name := line
switch {
case len(nameMatch) == 0:
case nameMatch[2] != "":
name = nameMatch[1]
withNoEncoding = true
case nameMatch[3] != "":
name = nameMatch[1]
withVersionField = true
if nameMatch[4] != "" {
flexible, err := strconv.Atoi(nameMatch[4])
if err != nil || flexible < 0 {
die("flexible version on line %q parse err: %v", line, err)
}
flexibleAt = flexible
fromFlexible = true
}
default: // simply "not top level"
name = nameMatch[1]
}

key := -1
Expand All @@ -377,6 +400,11 @@ func Parse(raw []byte) {
s.WithVersionField = withVersionField
s.WithNoEncoding = withNoEncoding
s.Key = key
if !topLevel && fromFlexible {
s.FromFlexible = fromFlexible
s.FlexibleAt = flexibleAt
}

s.BuildFrom(scanner, key, 0)
types[name] = s
newStructs = append(newStructs, s)
Expand Down Expand Up @@ -443,7 +471,7 @@ func Parse(raw []byte) {
die("missing flexible text on string ending with + in %q", rem)
} else {
flexible, err := strconv.Atoi(rem[idx+len(flexibleStr) : len(rem)-1])
if err != nil {
if err != nil || flexible < 0 {
die("flexible version on line %q parse err: %v", line, err)
}
s.FlexibleAt = flexible
Expand Down

0 comments on commit 724a2c1

Please sign in to comment.