Skip to content

Commit

Permalink
Merge pull request #15 from 200sc/release/v0.2.1
Browse files Browse the repository at this point in the history
Release/v0.2.1
  • Loading branch information
200sc authored Sep 12, 2021
2 parents 29c016a + 3dc974b commit f0bf67a
Show file tree
Hide file tree
Showing 88 changed files with 23,971 additions and 726 deletions.
7 changes: 1 addition & 6 deletions bebop.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,5 @@ type Const struct {
SimpleType string
Comment string
Name string
// GUIDs also use string values
StringValue *string
IntValue *int64
UIntValue *uint64
FloatValue *float64
BoolValue *bool
Value string
}
8 changes: 7 additions & 1 deletion compatibility_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ func skipIfUpstreamMissing(t *testing.T) {
}

func TestUpstreamCompatiblitySuccess(t *testing.T) {
if testing.Short() {
t.Skip("upstream tests skipped by --short")
}
skipIfUpstreamMissing(t)

cmd := exec.Command(upsteamCompilerName, "--ts", "./out.ts", "--dir", filepath.Join(".", "testdata", "base"))
Expand All @@ -29,6 +32,9 @@ func TestUpstreamCompatiblitySuccess(t *testing.T) {
}

func TestUpstreamCompatiblityFailures(t *testing.T) {
if testing.Short() {
t.Skip("upstream tests skipped by --short")
}
skipIfUpstreamMissing(t)

files, err := os.ReadDir(filepath.Join(".", "testdata", "invalid"))
Expand All @@ -37,7 +43,7 @@ func TestUpstreamCompatiblityFailures(t *testing.T) {
}

var exceptions = map[string]string{
"invalid_nested_union.bop": "merged into upstream but unreleased",
"invalid_readonly_comment.bop": "bebopc 2.2.4 errors where 2.3.0 does not, without a changelog note",
}

for _, f := range files {
Expand Down
59 changes: 2 additions & 57 deletions equality_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package bebop

import (
"fmt"
"math"
)

func (f File) equals(f2 File) error {
Expand Down Expand Up @@ -235,62 +234,8 @@ func (c Const) equals(c2 Const) error {
if c.Name != c2.Name {
return fmt.Errorf("name mismatch: %v vs %v", c.Name, c2.Name)
}
if (c.IntValue == nil) != (c2.IntValue == nil) {
return fmt.Errorf("const has int value type mismatch: %v vs %v", c.IntValue != nil, c2.IntValue != nil)
}
if c.IntValue != nil && c2.IntValue != nil {
if *c.IntValue != *c2.IntValue {
return fmt.Errorf("int value mismatch: %v vs %v", *c.IntValue, *c2.IntValue)
}
}
if (c.UIntValue == nil) != (c2.UIntValue == nil) {
return fmt.Errorf("const has uint value type mismatch: %v vs %v", c.UIntValue != nil, c2.UIntValue != nil)
}
if c.UIntValue != nil && c2.UIntValue != nil {
if *c.UIntValue != *c2.UIntValue {
return fmt.Errorf("uint value mismatch: %v vs %v", *c.UIntValue, *c2.UIntValue)
}
}
if (c.FloatValue == nil) != (c2.FloatValue == nil) {
return fmt.Errorf("const has float value type mismatch: %v vs %v", c.FloatValue != nil, c2.FloatValue != nil)
}
if c.FloatValue != nil && c2.FloatValue != nil {
if !floatEquals(*c.FloatValue, *c2.FloatValue) {
return fmt.Errorf("float value mismatch: %v vs %v", *c.FloatValue, *c2.FloatValue)
}
}
if (c.BoolValue == nil) != (c2.BoolValue == nil) {
return fmt.Errorf("const has bool value type mismatch: %v vs %v", c.BoolValue != nil, c2.BoolValue != nil)
}
if c.BoolValue != nil && c2.BoolValue != nil {
if *c.BoolValue != *c2.BoolValue {
return fmt.Errorf("bool value mismatch: %v vs %v", *c.BoolValue, *c2.BoolValue)
}
}
if (c.StringValue == nil) != (c2.StringValue == nil) {
return fmt.Errorf("const has string value type mismatch: %v vs %v", c.StringValue != nil, c2.StringValue != nil)
}
if c.StringValue != nil && c2.StringValue != nil {
if *c.StringValue != *c2.StringValue {
return fmt.Errorf("string value mismatch: %v vs %v", *c.StringValue, *c2.StringValue)
}
if c.Value != c2.Value {
return fmt.Errorf("value mismatch: %v vs %v", c.Value, c2.Value)
}
return nil
}

func floatEquals(f1, f2 float64) bool {
// TODO: epsilon equality?
if f1 == f2 {
return true
}
if math.IsNaN(f1) && math.IsNaN(f2) {
return true
}
if math.IsInf(f1, 1) && math.IsInf(f2, 1) {
return true
}
if math.IsInf(f1, -1) && math.IsInf(f2, -1) {
return true
}
return false
}
4 changes: 2 additions & 2 deletions format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestTokenizeFormat(t *testing.T) {
if err != nil {
t.Fatalf("failed to open test file %s: %v", filename+".bop", err)
}
if _, err := ReadFile(f); err != nil {
if _, _, err := ReadFile(f); err != nil {
f.Close()
t.Fatalf("can not format unparseable files")
}
Expand Down Expand Up @@ -65,7 +65,7 @@ func TestTokenizeFormatIncompatible(t *testing.T) {
if err != nil {
t.Fatalf("failed to open test file %s: %v", filename+".bop", err)
}
if _, err := ReadFile(f); err != nil {
if _, _, err := ReadFile(f); err != nil {
f.Close()
t.Fatalf("can not format unparseable files")
}
Expand Down
37 changes: 7 additions & 30 deletions gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
"math"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -285,7 +284,7 @@ func (f File) Generate(w io.Writer, settings GenerateSettings) error {
if err != nil {
return fmt.Errorf("failed to open imported file %s: %w", imp.to, err)
}
impFile, err := ReadFile(impF)
impFile, _, err := ReadFile(impF)
if err != nil {
impF.Close()
return fmt.Errorf("failed to parse imported file %s: %w", imp.to, err)
Expand Down Expand Up @@ -495,13 +494,13 @@ func (con Const) impossibleGoConst() bool {
// at least not intuitively. This probagbly doesn't matter-- its rare to
// rely on inf or nan floating points anyway, and even if you could get these as
// consts you would need to use math.IsInf or math.IsNaN for many use cases.
if con.FloatValue != nil {
switch {
case math.IsInf(*con.FloatValue, 1):
if con.SimpleType == typeFloat32 || con.SimpleType == typeFloat64 {
switch con.Value {
case "math.Inf(-1)":
return true
case math.IsInf(*con.FloatValue, -1):
case "math.Inf(1)":
return true
case math.IsNaN(*con.FloatValue):
case "math.NaN()":
return true
}
}
Expand All @@ -510,29 +509,7 @@ func (con Const) impossibleGoConst() bool {

func (con Const) Generate(w io.Writer, settings GenerateSettings) {
writeComment(w, 0, con.Comment)
var val interface{}
switch {
case con.BoolValue != nil:
val = *con.BoolValue
case con.FloatValue != nil:
switch {
case math.IsInf(*con.FloatValue, 1):
val = "math.Inf(1)"
case math.IsInf(*con.FloatValue, -1):
val = "math.Inf(-1)"
case math.IsNaN(*con.FloatValue):
val = "math.NaN()"
default:
val = strconv.FormatFloat(*con.FloatValue, 'g', -1, 64)
}
case con.IntValue != nil:
val = *con.IntValue
case con.UIntValue != nil:
val = *con.UIntValue
case con.StringValue != nil:
val = fmt.Sprintf("%q", *con.StringValue)
}
writeLine(w, "\t%s = %v", exposeName(con.Name), val)
writeLine(w, "\t%s = %v", exposeName(con.Name), con.Value)
}

func writeFieldDefinition(fd Field, w io.Writer, readOnly bool, message bool, settings GenerateSettings) {
Expand Down
46 changes: 15 additions & 31 deletions gen_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,13 @@ type fieldWithNumber struct {
func (msg Message) generateMarshalBebopTo(w io.Writer, settings GenerateSettings, fields []fieldWithNumber) {
exposedName := exposeName(msg.Name)
writeLine(w, "func (bbp %s) MarshalBebopTo(buf []byte) int {", exposedName)
if msg.OpCode != 0 {
writeLine(w, "\tiohelp.WriteUint32Bytes(buf, uint32(%sOpCode))", exposedName)
writeLine(w, "\tat := 4")
writeLine(w, "\tiohelp.WriteUint32Bytes(buf[at:], uint32(bbp.Size()-8))")
} else {
writeLine(w, "\tat := 0")
writeLine(w, "\tiohelp.WriteUint32Bytes(buf[at:], uint32(bbp.Size()-4))")
}
writeLine(w, "\tat := 0")
writeLine(w, "\tiohelp.WriteUint32Bytes(buf[at:], uint32(bbp.Size()-4))")
writeLine(w, "\tat += 4")
for _, fd := range fields {
if fd.Deprecated {
continue
}
name := exposeName(fd.Name)
num := strconv.Itoa(int(fd.num))
name = "*bbp." + name
Expand All @@ -42,11 +39,7 @@ func (msg Message) generateMarshalBebopTo(w io.Writer, settings GenerateSettings
func (msg Message) generateUnmarshalBebop(w io.Writer, settings GenerateSettings, fields []fieldWithNumber) {
exposedName := exposeName(msg.Name)
writeLine(w, "func (bbp *%s) UnmarshalBebop(buf []byte) (err error) {", exposedName)
if msg.OpCode != 0 {
writeLine(w, "\tat := 4")
} else {
writeLine(w, "\tat := 0")
}
writeLine(w, "\tat := 0")
writeLine(w, "\t_ = iohelp.ReadUint32Bytes(buf[at:])")
writeLine(w, "\tbuf = buf[4:]")
writeLine(w, "\tfor {")
Expand All @@ -68,11 +61,7 @@ func (msg Message) generateUnmarshalBebop(w io.Writer, settings GenerateSettings
func (msg Message) generateMustUnmarshalBebop(w io.Writer, settings GenerateSettings, fields []fieldWithNumber) {
exposedName := exposeName(msg.Name)
writeLine(w, "func (bbp *%s) MustUnmarshalBebop(buf []byte) {", exposedName)
if msg.OpCode != 0 {
writeLine(w, "\tat := 4")
} else {
writeLine(w, "\tat := 0")
}
writeLine(w, "\tat := 0")
writeLine(w, "\t_ = iohelp.ReadUint32Bytes(buf[at:])")
writeLine(w, "\tbuf = buf[4:]")
writeLine(w, "\tfor {")
Expand All @@ -96,13 +85,11 @@ func (msg Message) generateEncodeBebop(w io.Writer, settings GenerateSettings, f
*settings.isFirstTopLength = true
writeLine(w, "func (bbp %s) EncodeBebop(iow io.Writer) (err error) {", exposedName)
writeLine(w, "\tw := iohelp.NewErrorWriter(iow)")
if msg.OpCode != 0 {
writeLine(w, "\tiohelp.WriteUint32(w, uint32(%sOpCode))", exposedName)
writeLine(w, "\tiohelp.WriteUint32(w, uint32(bbp.Size()-8))")
} else {
writeLine(w, "\tiohelp.WriteUint32(w, uint32(bbp.Size()-4))")
}
writeLine(w, "\tiohelp.WriteUint32(w, uint32(bbp.Size()-4))")
for _, fd := range fields {
if fd.Deprecated {
continue
}
name := exposeName(fd.Name)
num := strconv.Itoa(int(fd.num))
name = "*bbp." + name
Expand All @@ -121,9 +108,6 @@ func (msg Message) generateDecodeBebop(w io.Writer, settings GenerateSettings, f
*settings.isFirstTopLength = true
writeLine(w, "func (bbp *%s) DecodeBebop(ior io.Reader) (err error) {", exposedName)
writeLine(w, "\tr := iohelp.NewErrorReader(ior)")
if msg.OpCode != 0 {
writeLine(w, "\tiohelp.ReadUint32(r)")
}
writeLine(w, "\tbodyLen := iohelp.ReadUint32(r)")
writeLine(w, "\tr.Reader = &io.LimitedReader{R:r.Reader, N:int64(bodyLen)}")
writeLine(w, "\tfor {")
Expand Down Expand Up @@ -152,10 +136,10 @@ func (msg Message) generateSize(w io.Writer, settings GenerateSettings, fields [
// a: (I think) because then we can loop reading a single byte for each field, and if we read 0
// we know we're done and don't have to unread the byte
writeLine(w, "\tbodyLen := 5")
if msg.OpCode != 0 {
writeLine(w, "\tbodyLen += 4")
}
for _, fd := range fields {
if fd.Deprecated {
continue
}
name := exposeName(fd.Name)
name = "*bbp." + name
writeLineWithTabs(w, "if %RECV != nil {", 1, name)
Expand Down Expand Up @@ -188,7 +172,7 @@ func (msg Message) Generate(w io.Writer, settings GenerateSettings) {
msg.generateEncodeBebop(w, settings, fields)
msg.generateDecodeBebop(w, settings, fields)
msg.generateSize(w, settings, fields)
isEmpty := len(msg.Fields) == 0 && msg.OpCode == 0
isEmpty := len(msg.Fields) == 0
writeWrappers(w, msg.Name, isEmpty, settings)
}

Expand Down
42 changes: 8 additions & 34 deletions gen_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ func (st Struct) generateMarshalBebopTo(w io.Writer, settings GenerateSettings)
exposedName := exposeName(st.Name)
writeLine(w, "func (bbp %s) MarshalBebopTo(buf []byte) int {", exposedName)
startAt := "0"
if st.OpCode != 0 {
writeLine(w, "\tiohelp.WriteUint32Bytes(buf, uint32(%sOpCode))", exposedName)
startAt = "4"
}
if len(st.Fields) == 0 {
writeLine(w, "\treturn "+startAt)
writeCloseBlock(w)
Expand All @@ -45,14 +41,8 @@ func (st Struct) generateMarshalBebopTo(w io.Writer, settings GenerateSettings)
func (st Struct) generateUnmarshalBebop(w io.Writer, settings GenerateSettings) {
exposedName := exposeName(st.Name)
writeLine(w, "func (bbp *%s) UnmarshalBebop(buf []byte) (err error) {", exposedName)
if st.OpCode != 0 {
if len(st.Fields) > 0 {
writeLine(w, "\tat := 4")
}
} else {
if len(st.Fields) > 0 {
writeLine(w, "\tat := 0")
}
if len(st.Fields) > 0 {
writeLine(w, "\tat := 0")
}
for _, fd := range st.Fields {
name := exposeName(fd.Name)
Expand All @@ -68,14 +58,8 @@ func (st Struct) generateUnmarshalBebop(w io.Writer, settings GenerateSettings)
func (st Struct) generateMustUnmarshalBebop(w io.Writer, settings GenerateSettings) {
exposedName := exposeName(st.Name)
writeLine(w, "func (bbp *%s) MustUnmarshalBebop(buf []byte) {", exposedName)
if st.OpCode != 0 {
if len(st.Fields) > 0 {
writeLine(w, "\tat := 4")
}
} else {
if len(st.Fields) > 0 {
writeLine(w, "\tat := 0")
}
if len(st.Fields) > 0 {
writeLine(w, "\tat := 0")
}
for _, fd := range st.Fields {
name := exposeName(fd.Name)
Expand All @@ -91,13 +75,10 @@ func (st Struct) generateEncodeBebop(w io.Writer, settings GenerateSettings) {
exposedName := exposeName(st.Name)
*settings.isFirstTopLength = true
writeLine(w, "func (bbp %s) EncodeBebop(iow io.Writer) (err error) {", exposedName)
if len(st.Fields) == 0 && st.OpCode == 0 {
if len(st.Fields) == 0 {
writeLine(w, "\treturn nil")
} else {
writeLine(w, "\tw := iohelp.NewErrorWriter(iow)")
if st.OpCode != 0 {
writeLine(w, "\tiohelp.WriteUint32(w, uint32(%sOpCode))", exposedName)
}
for _, fd := range st.Fields {
name := exposeName(fd.Name)
if st.ReadOnly {
Expand All @@ -114,14 +95,10 @@ func (st Struct) generateDecodeBebop(w io.Writer, settings GenerateSettings) {
exposedName := exposeName(st.Name)
*settings.isFirstTopLength = true
writeLine(w, "func (bbp *%s) DecodeBebop(ior io.Reader) (err error) {", exposedName)
if len(st.Fields) == 0 && st.OpCode == 0 {
if len(st.Fields) == 0 {
writeLine(w, "\treturn nil")
} else {
writeLine(w, "\tr := iohelp.NewErrorReader(ior)")
if st.OpCode != 0 {
writeLine(w, "\tr.Read(make([]byte, 4))")
writeLine(w, "\tif r.Err != nil {\n\t\treturn r.Err\n\t}")
}
for _, fd := range st.Fields {
name := exposeName(fd.Name)
if st.ReadOnly {
Expand All @@ -137,13 +114,10 @@ func (st Struct) generateDecodeBebop(w io.Writer, settings GenerateSettings) {
func (st Struct) generateSize(w io.Writer, settings GenerateSettings) {
exposedName := exposeName(st.Name)
writeLine(w, "func (bbp %s) Size() int {", exposedName)
if len(st.Fields) == 0 && st.OpCode == 0 {
if len(st.Fields) == 0 {
writeLine(w, "\treturn 0")
} else {
writeLine(w, "\tbodyLen := 0")
if st.OpCode != 0 {
writeLine(w, "\tbodyLen += 4")
}
for _, fd := range st.Fields {
name := exposeName(fd.Name)
if st.ReadOnly {
Expand Down Expand Up @@ -190,7 +164,7 @@ func (st Struct) Generate(w io.Writer, settings GenerateSettings) {
st.generateDecodeBebop(w, settings)
st.generateSize(w, settings)

isEmpty := len(st.Fields) == 0 && st.OpCode == 0
isEmpty := len(st.Fields) == 0
writeWrappers(w, st.Name, isEmpty, settings)
if st.ReadOnly {
st.generateReadOnlyGetters(w, settings)
Expand Down
Loading

0 comments on commit f0bf67a

Please sign in to comment.