diff --git a/build.sh b/build.sh index a450e05..087e24b 100755 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -VERSION="0.2.1" +VERSION="0.2.2" PROTECTED_MODE="no" export GO15VENDOREXPERIMENT=1 diff --git a/vendor/github.com/tidwall/sjson/sjson.go b/vendor/github.com/tidwall/sjson/sjson.go index df6581c..7f1d358 100644 --- a/vendor/github.com/tidwall/sjson/sjson.go +++ b/vendor/github.com/tidwall/sjson/sjson.go @@ -18,7 +18,7 @@ func (err *errorType) Error() string { return err.msg } -// Options represents addtional options for the Set and Delete functions. +// Options represents additional options for the Set and Delete functions. type Options struct { // Optimistic is a hint that the value likely exists which // allows for the sjson to perform a fast-track search and replace. @@ -26,7 +26,9 @@ type Options struct { // ReplaceInPlace is a hint to replace the input json rather than // allocate a new json byte slice. When this field is specified // the input json will not longer be valid and it should not be used - // There is no guarentees that the memory will be replaced in-place. + // In the case when the destination slice doesn't have enough free + // bytes to replace the data in place, a new bytes slice will be + // created under the hood. // The Optimistic flag must be set to true and the input must be a // byte slice in order to use this field. ReplaceInPlace bool @@ -126,7 +128,7 @@ func appendBuild(buf []byte, array bool, paths []pathResult, raw string, } if len(paths) > 1 { n, numeric := atoui(paths[1]) - if numeric { + if numeric || (!paths[1].force && paths[1].part == "-1") { buf = append(buf, '[') buf = appendRepeat(buf, "null,", n) buf = appendBuild(buf, true, paths[1:], raw, stringify) @@ -261,7 +263,7 @@ func appendRawPaths(buf []byte, jstr string, paths []pathResult, raw string, return buf, nil } buf = append(buf, jstr[:res.Index]...) - var exidx int // addional forward stripping + var exidx int // additional forward stripping if del { var delNextComma bool buf, delNextComma = deleteTailItem(buf) @@ -470,7 +472,7 @@ func set(jstr, path, raw string, // Invalid json will not panic, but it may return back unexpected results. // An error is returned if the path is not valid. // -// A path is a series of keys seperated by a dot. +// A path is a series of keys separated by a dot. // // { // "name": {"first": "Tom", "last": "Anderson"}, @@ -635,7 +637,7 @@ func SetRawBytesOptions(json []byte, path string, value []byte, if err == errNoChange { return json, nil } - return res, nil + return res, err } type dtype struct{} diff --git a/vendor/github.com/tidwall/sjson/sjson_test.go b/vendor/github.com/tidwall/sjson/sjson_test.go index 08f7e29..a7a8f7e 100644 --- a/vendor/github.com/tidwall/sjson/sjson_test.go +++ b/vendor/github.com/tidwall/sjson/sjson_test.go @@ -3,10 +3,18 @@ package sjson import ( "bytes" "encoding/hex" + gojson "encoding/json" + "fmt" "math/rand" "strings" "testing" "time" + + "github.com/Jeffail/gabs" + + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" + fflib "github.com/pquerna/ffjson/fflib/v1" ) func TestInvalidPaths(t *testing.T) { @@ -133,6 +141,7 @@ func TestBasic(t *testing.T) { testRaw(t, setString, `["1234.5"]`, ``, `0`, "1234.5") testRaw(t, setBool, `[true]`, ``, `0`, true) testRaw(t, setBool, `[null]`, ``, `0`, nil) + testRaw(t, setString, `{"arr":[1]}`, ``, `arr.-1`, 1) } func TestDelete(t *testing.T) { @@ -169,7 +178,7 @@ func TestRandomData(t *testing.T) { } } -var json = ` +var exampleJSON = ` { "sha": "d25341478381063d1c76e81b3a52e0592a7c997f", "commit": { @@ -197,9 +206,9 @@ var path = "commit.committer.email" var value = "tomtom@anderson.com" var rawValue = `"tomtom@anderson.com"` var rawValueBytes = []byte(rawValue) -var expect = strings.Replace(json, "jeffditto@anderson.edu", "tomtom@anderson.com", 1) -var jsonBytes = []byte(json) -var jsonBytes2 = []byte(json) +var expect = strings.Replace(exampleJSON, "jeffditto@anderson.edu", "tomtom@anderson.com", 1) +var jsonBytes = []byte(exampleJSON) +var jsonBytes2 = []byte(exampleJSON) var expectBytes = []byte(expect) var opts = &Options{Optimistic: true} var optsInPlace = &Options{Optimistic: true, ReplaceInPlace: true} @@ -207,7 +216,7 @@ var optsInPlace = &Options{Optimistic: true, ReplaceInPlace: true} func BenchmarkSet(t *testing.B) { t.ReportAllocs() for i := 0; i < t.N; i++ { - res, err := Set(json, path, value) + res, err := Set(exampleJSON, path, value) if err != nil { t.Fatal(err) } @@ -220,7 +229,7 @@ func BenchmarkSet(t *testing.B) { func BenchmarkSetRaw(t *testing.B) { t.ReportAllocs() for i := 0; i < t.N; i++ { - res, err := SetRaw(json, path, rawValue) + res, err := SetRaw(exampleJSON, path, rawValue) if err != nil { t.Fatal(err) } @@ -259,7 +268,7 @@ func BenchmarkSetRawBytes(t *testing.B) { func BenchmarkSetOptimistic(t *testing.B) { t.ReportAllocs() for i := 0; i < t.N; i++ { - res, err := SetOptions(json, path, value, opts) + res, err := SetOptions(exampleJSON, path, value, opts) if err != nil { t.Fatal(err) } @@ -272,7 +281,7 @@ func BenchmarkSetOptimistic(t *testing.B) { func BenchmarkSetInPlace(t *testing.B) { t.ReportAllocs() for i := 0; i < t.N; i++ { - res, err := SetOptions(json, path, value, optsInPlace) + res, err := SetOptions(exampleJSON, path, value, optsInPlace) if err != nil { t.Fatal(err) } @@ -285,7 +294,7 @@ func BenchmarkSetInPlace(t *testing.B) { func BenchmarkSetRawOptimistic(t *testing.B) { t.ReportAllocs() for i := 0; i < t.N; i++ { - res, err := SetRawOptions(json, path, rawValue, opts) + res, err := SetRawOptions(exampleJSON, path, rawValue, opts) if err != nil { t.Fatal(err) } @@ -298,7 +307,7 @@ func BenchmarkSetRawOptimistic(t *testing.B) { func BenchmarkSetRawInPlace(t *testing.B) { t.ReportAllocs() for i := 0; i < t.N; i++ { - res, err := SetRawOptions(json, path, rawValue, optsInPlace) + res, err := SetRawOptions(exampleJSON, path, rawValue, optsInPlace) if err != nil { t.Fatal(err) } @@ -361,3 +370,870 @@ func BenchmarkSetRawBytesInPlace(t *testing.B) { } } } + +const benchJSON = ` +{ + "widget": { + "debug": "on", + "window": { + "title": "Sample Konfabulator Widget", + "name": "main_window", + "width": 500, + "height": 500 + }, + "image": { + "src": "Images/Sun.png", + "hOffset": 250, + "vOffset": 250, + "alignment": "center" + }, + "text": { + "data": "Click Here", + "size": 36, + "style": "bold", + "vOffset": 100, + "alignment": "center", + "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" + } + } +} +` + +type BenchStruct struct { + Widget struct { + Debug string `json:"debug"` + Window struct { + Title string `json:"title"` + Name string `json:"name"` + Width int `json:"width"` + Height int `json:"height"` + } `json:"window"` + Image struct { + Src string `json:"src"` + HOffset int `json:"hOffset"` + VOffset int `json:"vOffset"` + Alignment string `json:"alignment"` + } `json:"image"` + Text struct { + Data string `json:"data"` + Size int `json:"size"` + Style string `json:"style"` + VOffset int `json:"vOffset"` + Alignment string `json:"alignment"` + OnMouseUp string `json:"onMouseUp"` + } `json:"text"` + } `json:"widget"` +} + +var benchPaths = []string{ + "widget.window.name", + "widget.image.hOffset", + "widget.text.onMouseUp", +} + +func Benchmark_SJSON(t *testing.B) { + opts := Options{Optimistic: true} + t.ReportAllocs() + t.ResetTimer() + for i := 0; i < t.N; i++ { + for _, path := range benchPaths { + var err error + switch path { + case "widget.window.name": + _, err = SetOptions(benchJSON, path, "1", &opts) + case "widget.image.hOffset": + _, err = SetOptions(benchJSON, path, 1, &opts) + case "widget.text.onMouseUp": + _, err = SetOptions(benchJSON, path, "1", &opts) + } + if err != nil { + t.Fatal(err) + } + + } + } + t.N *= len(benchPaths) +} + +func Benchmark_SJSON_ReplaceInPlace(t *testing.B) { + data := []byte(benchJSON) + opts := Options{ + Optimistic: true, + ReplaceInPlace: true, + } + v1, v2 := []byte(`"1"`), []byte("1") + t.ReportAllocs() + t.ResetTimer() + for i := 0; i < t.N; i++ { + for _, path := range benchPaths { + var err error + switch path { + case "widget.window.name": + _, err = SetRawBytesOptions(data, path, v1, &opts) + case "widget.image.hOffset": + _, err = SetRawBytesOptions(data, path, v2, &opts) + case "widget.text.onMouseUp": + _, err = SetRawBytesOptions(data, path, v1, &opts) + } + if err != nil { + t.Fatal(err) + } + + } + } + t.N *= len(benchPaths) +} + +func Benchmark_Encoding_JSON_Map(t *testing.B) { + data := []byte(benchJSON) + t.ReportAllocs() + t.ResetTimer() + for i := 0; i < t.N; i++ { + for _, path := range benchPaths { + var m map[string]interface{} + if err := gojson.Unmarshal(data, &m); err != nil { + t.Fatal(err) + } + switch path { + case "widget.window.name": + m["widget"].(map[string]interface{})["window"].(map[string]interface{})["name"] = "1" + case "widget.image.hOffset": + m["widget"].(map[string]interface{})["image"].(map[string]interface{})["hOffset"] = 1 + case "widget.text.onMouseUp": + m["widget"].(map[string]interface{})["text"].(map[string]interface{})["onMouseUp"] = "1" + } + _, err := gojson.Marshal(&m) + if err != nil { + t.Fatal(err) + } + } + } + t.N *= len(benchPaths) +} + +func Benchmark_Encoding_JSON_Struct(t *testing.B) { + data := []byte(benchJSON) + t.ReportAllocs() + t.ResetTimer() + for i := 0; i < t.N; i++ { + for _, path := range benchPaths { + var v BenchStruct + if err := gojson.Unmarshal(data, &v); err != nil { + t.Fatal(err) + } + switch path { + case "widget.window.name": + v.Widget.Window.Name = "1" + case "widget.image.hOffset": + v.Widget.Image.HOffset = 1 + case "widget.text.onMouseUp": + v.Widget.Text.OnMouseUp = "1" + } + _, err := gojson.Marshal(&v) + if err != nil { + t.Fatal(err) + } + } + } + t.N *= len(benchPaths) +} + +func Benchmark_Gabs(t *testing.B) { + data := []byte(benchJSON) + t.ReportAllocs() + t.ResetTimer() + for i := 0; i < t.N; i++ { + for _, path := range benchPaths { + jsonParsed, err := gabs.ParseJSON(data) + if err != nil { + t.Fatal(err) + } + switch path { + case "widget.window.name": + jsonParsed.SetP("1", path) + case "widget.image.hOffset": + jsonParsed.SetP(1, path) + case "widget.text.onMouseUp": + jsonParsed.SetP("1", path) + } + jsonParsed.String() + } + } + t.N *= len(benchPaths) +} + +func Benchmark_FFJSON(t *testing.B) { + data := []byte(benchJSON) + t.ReportAllocs() + t.ResetTimer() + for i := 0; i < t.N; i++ { + for _, path := range benchPaths { + var v BenchStruct + if err := v.UnmarshalFFJSONFromData(data); err != nil { + t.Fatal(err) + } + switch path { + case "widget.window.name": + v.Widget.Window.Name = "1" + case "widget.image.hOffset": + v.Widget.Image.HOffset = 1 + case "widget.text.onMouseUp": + v.Widget.Text.OnMouseUp = "1" + } + _, err := v.MarshalFFJSONFromData() + if err != nil { + t.Fatal(err) + } + } + } + t.N *= len(benchPaths) +} + +func Benchmark_EasyJSON(t *testing.B) { + data := []byte(benchJSON) + t.ReportAllocs() + t.ResetTimer() + for i := 0; i < t.N; i++ { + for _, path := range benchPaths { + var v BenchStruct + if err := v.UnmarshalEasyJSONFromData(data); err != nil { + t.Fatal(err) + } + switch path { + case "widget.window.name": + v.Widget.Window.Name = "1" + case "widget.image.hOffset": + v.Widget.Image.HOffset = 1 + case "widget.text.onMouseUp": + v.Widget.Text.OnMouseUp = "1" + } + _, err := v.MarshalEasyJSONFromData() + if err != nil { + t.Fatal(err) + } + } + } + t.N *= len(benchPaths) +} + +////////////////////////////////////////////////////////////// +// EVERYTHING BELOW IS AUTOGENERATED + +// suppress unused package warning +var ( + _ = gojson.RawMessage{} + _ = jlexer.Lexer{} + _ = jwriter.Writer{} +) + +func easyjsonDbb23193DecodeGithubComTidwallSjson(in *jlexer.Lexer, out *BenchStruct) { + if in.IsNull() { + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "widget": + easyjsonDbb23193Decode(in, &out.Widget) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') +} +func easyjsonDbb23193EncodeGithubComTidwallSjson(out *jwriter.Writer, in BenchStruct) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"widget\":") + easyjsonDbb23193Encode(out, in.Widget) + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v BenchStruct) MarshalEasyJSONFromData() ([]byte, error) { + w := jwriter.Writer{} + easyjsonDbb23193EncodeGithubComTidwallSjson(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v BenchStruct) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDbb23193EncodeGithubComTidwallSjson(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *BenchStruct) UnmarshalEasyJSONFromData(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonDbb23193DecodeGithubComTidwallSjson(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *BenchStruct) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDbb23193DecodeGithubComTidwallSjson(l, v) +} +func easyjsonDbb23193Decode(in *jlexer.Lexer, out *struct { + Debug string "json:\"debug\"" + Window struct { + Title string "json:\"title\"" + Name string "json:\"name\"" + Width int "json:\"width\"" + Height int "json:\"height\"" + } "json:\"window\"" + Image struct { + Src string "json:\"src\"" + HOffset int "json:\"hOffset\"" + VOffset int "json:\"vOffset\"" + Alignment string "json:\"alignment\"" + } "json:\"image\"" + Text struct { + Data string "json:\"data\"" + Size int "json:\"size\"" + Style string "json:\"style\"" + VOffset int "json:\"vOffset\"" + Alignment string "json:\"alignment\"" + OnMouseUp string "json:\"onMouseUp\"" + } "json:\"text\"" +}) { + if in.IsNull() { + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "debug": + out.Debug = string(in.String()) + case "window": + easyjsonDbb23193Decode1(in, &out.Window) + case "image": + easyjsonDbb23193Decode2(in, &out.Image) + case "text": + easyjsonDbb23193Decode3(in, &out.Text) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') +} +func easyjsonDbb23193Encode(out *jwriter.Writer, in struct { + Debug string "json:\"debug\"" + Window struct { + Title string "json:\"title\"" + Name string "json:\"name\"" + Width int "json:\"width\"" + Height int "json:\"height\"" + } "json:\"window\"" + Image struct { + Src string "json:\"src\"" + HOffset int "json:\"hOffset\"" + VOffset int "json:\"vOffset\"" + Alignment string "json:\"alignment\"" + } "json:\"image\"" + Text struct { + Data string "json:\"data\"" + Size int "json:\"size\"" + Style string "json:\"style\"" + VOffset int "json:\"vOffset\"" + Alignment string "json:\"alignment\"" + OnMouseUp string "json:\"onMouseUp\"" + } "json:\"text\"" +}) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"debug\":") + out.String(string(in.Debug)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"window\":") + easyjsonDbb23193Encode1(out, in.Window) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"image\":") + easyjsonDbb23193Encode2(out, in.Image) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"text\":") + easyjsonDbb23193Encode3(out, in.Text) + out.RawByte('}') +} +func easyjsonDbb23193Decode3(in *jlexer.Lexer, out *struct { + Data string "json:\"data\"" + Size int "json:\"size\"" + Style string "json:\"style\"" + VOffset int "json:\"vOffset\"" + Alignment string "json:\"alignment\"" + OnMouseUp string "json:\"onMouseUp\"" +}) { + if in.IsNull() { + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "data": + out.Data = string(in.String()) + case "size": + out.Size = int(in.Int()) + case "style": + out.Style = string(in.String()) + case "vOffset": + out.VOffset = int(in.Int()) + case "alignment": + out.Alignment = string(in.String()) + case "onMouseUp": + out.OnMouseUp = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') +} +func easyjsonDbb23193Encode3(out *jwriter.Writer, in struct { + Data string "json:\"data\"" + Size int "json:\"size\"" + Style string "json:\"style\"" + VOffset int "json:\"vOffset\"" + Alignment string "json:\"alignment\"" + OnMouseUp string "json:\"onMouseUp\"" +}) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"data\":") + out.String(string(in.Data)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"size\":") + out.Int(int(in.Size)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"style\":") + out.String(string(in.Style)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"vOffset\":") + out.Int(int(in.VOffset)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"alignment\":") + out.String(string(in.Alignment)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"onMouseUp\":") + out.String(string(in.OnMouseUp)) + out.RawByte('}') +} +func easyjsonDbb23193Decode2(in *jlexer.Lexer, out *struct { + Src string "json:\"src\"" + HOffset int "json:\"hOffset\"" + VOffset int "json:\"vOffset\"" + Alignment string "json:\"alignment\"" +}) { + if in.IsNull() { + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "src": + out.Src = string(in.String()) + case "hOffset": + out.HOffset = int(in.Int()) + case "vOffset": + out.VOffset = int(in.Int()) + case "alignment": + out.Alignment = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') +} +func easyjsonDbb23193Encode2(out *jwriter.Writer, in struct { + Src string "json:\"src\"" + HOffset int "json:\"hOffset\"" + VOffset int "json:\"vOffset\"" + Alignment string "json:\"alignment\"" +}) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"src\":") + out.String(string(in.Src)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"hOffset\":") + out.Int(int(in.HOffset)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"vOffset\":") + out.Int(int(in.VOffset)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"alignment\":") + out.String(string(in.Alignment)) + out.RawByte('}') +} +func easyjsonDbb23193Decode1(in *jlexer.Lexer, out *struct { + Title string "json:\"title\"" + Name string "json:\"name\"" + Width int "json:\"width\"" + Height int "json:\"height\"" +}) { + if in.IsNull() { + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "title": + out.Title = string(in.String()) + case "name": + out.Name = string(in.String()) + case "width": + out.Width = int(in.Int()) + case "height": + out.Height = int(in.Int()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') +} +func easyjsonDbb23193Encode1(out *jwriter.Writer, in struct { + Title string "json:\"title\"" + Name string "json:\"name\"" + Width int "json:\"width\"" + Height int "json:\"height\"" +}) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"title\":") + out.String(string(in.Title)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"name\":") + out.String(string(in.Name)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"width\":") + out.Int(int(in.Width)) + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"height\":") + out.Int(int(in.Height)) + out.RawByte('}') +} +func (mj *BenchStruct) MarshalFFJSONFromData() ([]byte, error) { + var buf fflib.Buffer + if mj == nil { + buf.WriteString("null") + return buf.Bytes(), nil + } + err := mj.MarshalJSONBufFFJSON(&buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} +func (mj *BenchStruct) MarshalJSONBufFFJSON(buf fflib.EncodingBuffer) error { + if mj == nil { + buf.WriteString("null") + return nil + } + var err error + var obj []byte + _ = obj + _ = err + /* Inline struct. type=struct { Debug string "json:\"debug\""; Window struct { Title string "json:\"title\""; Name string "json:\"name\""; Width int "json:\"width\""; Height int "json:\"height\"" } "json:\"window\""; Image struct { Src string "json:\"src\""; HOffset int "json:\"hOffset\""; VOffset int "json:\"vOffset\""; Alignment string "json:\"alignment\"" } "json:\"image\""; Text struct { Data string "json:\"data\""; Size int "json:\"size\""; Style string "json:\"style\""; VOffset int "json:\"vOffset\""; Alignment string "json:\"alignment\""; OnMouseUp string "json:\"onMouseUp\"" } "json:\"text\"" } kind=struct */ + buf.WriteString(`{"widget":{ "debug":`) + fflib.WriteJsonString(buf, string(mj.Widget.Debug)) + /* Inline struct. type=struct { Title string "json:\"title\""; Name string "json:\"name\""; Width int "json:\"width\""; Height int "json:\"height\"" } kind=struct */ + buf.WriteString(`,"window":{ "title":`) + fflib.WriteJsonString(buf, string(mj.Widget.Window.Title)) + buf.WriteString(`,"name":`) + fflib.WriteJsonString(buf, string(mj.Widget.Window.Name)) + buf.WriteString(`,"width":`) + fflib.FormatBits2(buf, uint64(mj.Widget.Window.Width), 10, mj.Widget.Window.Width < 0) + buf.WriteString(`,"height":`) + fflib.FormatBits2(buf, uint64(mj.Widget.Window.Height), 10, mj.Widget.Window.Height < 0) + buf.WriteByte('}') + /* Inline struct. type=struct { Src string "json:\"src\""; HOffset int "json:\"hOffset\""; VOffset int "json:\"vOffset\""; Alignment string "json:\"alignment\"" } kind=struct */ + buf.WriteString(`,"image":{ "src":`) + fflib.WriteJsonString(buf, string(mj.Widget.Image.Src)) + buf.WriteString(`,"hOffset":`) + fflib.FormatBits2(buf, uint64(mj.Widget.Image.HOffset), 10, mj.Widget.Image.HOffset < 0) + buf.WriteString(`,"vOffset":`) + fflib.FormatBits2(buf, uint64(mj.Widget.Image.VOffset), 10, mj.Widget.Image.VOffset < 0) + buf.WriteString(`,"alignment":`) + fflib.WriteJsonString(buf, string(mj.Widget.Image.Alignment)) + buf.WriteByte('}') + /* Inline struct. type=struct { Data string "json:\"data\""; Size int "json:\"size\""; Style string "json:\"style\""; VOffset int "json:\"vOffset\""; Alignment string "json:\"alignment\""; OnMouseUp string "json:\"onMouseUp\"" } kind=struct */ + buf.WriteString(`,"text":{ "data":`) + fflib.WriteJsonString(buf, string(mj.Widget.Text.Data)) + buf.WriteString(`,"size":`) + fflib.FormatBits2(buf, uint64(mj.Widget.Text.Size), 10, mj.Widget.Text.Size < 0) + buf.WriteString(`,"style":`) + fflib.WriteJsonString(buf, string(mj.Widget.Text.Style)) + buf.WriteString(`,"vOffset":`) + fflib.FormatBits2(buf, uint64(mj.Widget.Text.VOffset), 10, mj.Widget.Text.VOffset < 0) + buf.WriteString(`,"alignment":`) + fflib.WriteJsonString(buf, string(mj.Widget.Text.Alignment)) + buf.WriteString(`,"onMouseUp":`) + fflib.WriteJsonString(buf, string(mj.Widget.Text.OnMouseUp)) + buf.WriteByte('}') + buf.WriteByte('}') + buf.WriteByte('}') + return nil +} + +const ( + ffj_t_BenchStructbase = iota + ffj_t_BenchStructno_such_key + + ffj_t_BenchStruct_Widget +) + +var ffj_key_BenchStruct_Widget = []byte("widget") + +func (uj *BenchStruct) UnmarshalFFJSONFromData(input []byte) error { + fs := fflib.NewFFLexer(input) + return uj.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) +} + +func (uj *BenchStruct) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { + var err error = nil + currentKey := ffj_t_BenchStructbase + _ = currentKey + tok := fflib.FFTok_init + wantedTok := fflib.FFTok_init + +mainparse: + for { + tok = fs.Scan() + // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) + if tok == fflib.FFTok_error { + goto tokerror + } + + switch state { + + case fflib.FFParse_map_start: + if tok != fflib.FFTok_left_bracket { + wantedTok = fflib.FFTok_left_bracket + goto wrongtokenerror + } + state = fflib.FFParse_want_key + continue + + case fflib.FFParse_after_value: + if tok == fflib.FFTok_comma { + state = fflib.FFParse_want_key + } else if tok == fflib.FFTok_right_bracket { + goto done + } else { + wantedTok = fflib.FFTok_comma + goto wrongtokenerror + } + + case fflib.FFParse_want_key: + // json {} ended. goto exit. woo. + if tok == fflib.FFTok_right_bracket { + goto done + } + if tok != fflib.FFTok_string { + wantedTok = fflib.FFTok_string + goto wrongtokenerror + } + + kn := fs.Output.Bytes() + if len(kn) <= 0 { + // "" case. hrm. + currentKey = ffj_t_BenchStructno_such_key + state = fflib.FFParse_want_colon + goto mainparse + } else { + switch kn[0] { + + case 'w': + + if bytes.Equal(ffj_key_BenchStruct_Widget, kn) { + currentKey = ffj_t_BenchStruct_Widget + state = fflib.FFParse_want_colon + goto mainparse + } + + } + + if fflib.SimpleLetterEqualFold(ffj_key_BenchStruct_Widget, kn) { + currentKey = ffj_t_BenchStruct_Widget + state = fflib.FFParse_want_colon + goto mainparse + } + + currentKey = ffj_t_BenchStructno_such_key + state = fflib.FFParse_want_colon + goto mainparse + } + + case fflib.FFParse_want_colon: + if tok != fflib.FFTok_colon { + wantedTok = fflib.FFTok_colon + goto wrongtokenerror + } + state = fflib.FFParse_want_value + continue + case fflib.FFParse_want_value: + + if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { + switch currentKey { + + case ffj_t_BenchStruct_Widget: + goto handle_Widget + + case ffj_t_BenchStructno_such_key: + err = fs.SkipField(tok) + if err != nil { + return fs.WrapErr(err) + } + state = fflib.FFParse_after_value + goto mainparse + } + } else { + goto wantedvalue + } + } + } + +handle_Widget: + + /* handler: uj.Widget type=struct { Debug string "json:\"debug\""; Window struct { Title string "json:\"title\""; Name string "json:\"name\""; Width int "json:\"width\""; Height int "json:\"height\"" } "json:\"window\""; Image struct { Src string "json:\"src\""; HOffset int "json:\"hOffset\""; VOffset int "json:\"vOffset\""; Alignment string "json:\"alignment\"" } "json:\"image\""; Text struct { Data string "json:\"data\""; Size int "json:\"size\""; Style string "json:\"style\""; VOffset int "json:\"vOffset\""; Alignment string "json:\"alignment\""; OnMouseUp string "json:\"onMouseUp\"" } "json:\"text\"" } kind=struct quoted=false*/ + + { + /* Falling back. type=struct { Debug string "json:\"debug\""; Window struct { Title string "json:\"title\""; Name string "json:\"name\""; Width int "json:\"width\""; Height int "json:\"height\"" } "json:\"window\""; Image struct { Src string "json:\"src\""; HOffset int "json:\"hOffset\""; VOffset int "json:\"vOffset\""; Alignment string "json:\"alignment\"" } "json:\"image\""; Text struct { Data string "json:\"data\""; Size int "json:\"size\""; Style string "json:\"style\""; VOffset int "json:\"vOffset\""; Alignment string "json:\"alignment\""; OnMouseUp string "json:\"onMouseUp\"" } "json:\"text\"" } kind=struct */ + tbuf, err := fs.CaptureField(tok) + if err != nil { + return fs.WrapErr(err) + } + + err = gojson.Unmarshal(tbuf, &uj.Widget) + if err != nil { + return fs.WrapErr(err) + } + } + + state = fflib.FFParse_after_value + goto mainparse + +wantedvalue: + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) +wrongtokenerror: + return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) +tokerror: + if fs.BigError != nil { + return fs.WrapErr(fs.BigError) + } + err = fs.Error.ToError() + if err != nil { + return fs.WrapErr(err) + } + panic("ffjson-generated: unreachable, please report bug.") +done: + return nil +}