Fix stream decoding for null/true/false value

This commit is contained in:
Masaaki Goshima 2021-05-02 17:01:56 +09:00
parent 82cc22a37f
commit 2034757368
4 changed files with 108 additions and 70 deletions

View File

@ -13,54 +13,6 @@ func newBoolDecoder(structName, fieldName string) *boolDecoder {
return &boolDecoder{structName: structName, fieldName: fieldName}
}
func trueBytes(s *stream) error {
if s.cursor+3 >= s.length {
if !s.read() {
return errInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
}
}
s.cursor++
if s.char() != 'r' {
return errInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
}
s.cursor++
if s.char() != 'u' {
return errInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
}
s.cursor++
if s.char() != 'e' {
return errInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
}
s.cursor++
return nil
}
func falseBytes(s *stream) error {
if s.cursor+4 >= s.length {
if !s.read() {
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
}
}
s.cursor++
if s.char() != 'a' {
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
}
s.cursor++
if s.char() != 'l' {
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
}
s.cursor++
if s.char() != 's' {
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
}
s.cursor++
if s.char() != 'e' {
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
}
s.cursor++
return nil
}
func (d *boolDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace()
for {

View File

@ -313,3 +313,102 @@ func (s *stream) skipValue(depth int64) error {
cursor++
}
}
func nullBytes(s *stream) error {
// current cursor's character is 'n'
s.cursor++
if s.char() != 'u' {
if err := retryReadNull(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'l' {
if err := retryReadNull(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'l' {
if err := retryReadNull(s); err != nil {
return err
}
}
s.cursor++
return nil
}
func retryReadNull(s *stream) error {
if s.char() == nul && s.read() {
return nil
}
return errInvalidCharacter(s.char(), "null", s.totalOffset())
}
func trueBytes(s *stream) error {
// current cursor's character is 't'
s.cursor++
if s.char() != 'r' {
if err := retryReadTrue(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'u' {
if err := retryReadTrue(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'e' {
if err := retryReadTrue(s); err != nil {
return err
}
}
s.cursor++
return nil
}
func retryReadTrue(s *stream) error {
if s.char() == nul && s.read() {
return nil
}
return errInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
}
func falseBytes(s *stream) error {
// current cursor's character is 'f'
s.cursor++
if s.char() != 'a' {
if err := retryReadFalse(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'l' {
if err := retryReadFalse(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 's' {
if err := retryReadFalse(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'e' {
if err := retryReadFalse(s); err != nil {
return err
}
}
s.cursor++
return nil
}
func retryReadFalse(s *stream) error {
if s.char() == nul && s.read() {
return nil
}
return errInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
}

View File

@ -233,28 +233,6 @@ ERROR:
return nil, errUnexpectedEndOfJSON("string", s.totalOffset())
}
func nullBytes(s *stream) error {
if s.cursor+3 >= s.length {
if !s.read() {
return errInvalidCharacter(s.char(), "null", s.totalOffset())
}
}
s.cursor++
if s.char() != 'u' {
return errInvalidCharacter(s.char(), "null", s.totalOffset())
}
s.cursor++
if s.char() != 'l' {
return errInvalidCharacter(s.char(), "null", s.totalOffset())
}
s.cursor++
if s.char() != 'l' {
return errInvalidCharacter(s.char(), "null", s.totalOffset())
}
s.cursor++
return nil
}
func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) {
for {
switch s.char() {

View File

@ -32,6 +32,15 @@ func TestValid(t *testing.T) {
}
}
func TestValidWithComplexData(t *testing.T) {
data := []byte(`{"ABCDEFGHIJKL":[{"MNOPQRSTUVWX":[{"YABC":{"DEFG":[{"HIJKLMNO":{"PQRS":"TUVWXYABCDEFGHIJKLMNOPQRSTUVWXYABCDEFGHIJKLMNOPQRSTUVWXYABCDE","FGHIJKLM":"NOPQRSTUVW"},"XYABCDEFGH":[{"IJKLMNOP":"!=","Q":{"RSTU":"V","WXYABCDE":"FGHIJKLMNO"},"P":{"QRSTUVWX":"YAB"},"CDEFGHIJ":"KLMNOP","QRSTUVWX":"YABCDEFGHI"}],"JKLMNOPQRSTUVW":null,"XYABCDEF":"GHIJ"},{"KLMNOPQR":{"STUVWXY":{"ABCDEFGH":"IJKLMN_OPQ_RST","U":{"VWXY":"A","BCDEFGHI":"JKLMNOPQRS"},"TUVWXYAB":"CDEFG","HIJKLMNO":"PQRSTUVWXY"},"ABCDEFGH":"IJKLMNOP!Q41R8ST98U00V204W9800998XYA8427B","CDEFGHIJ":"KLMNOP","QRSTUVWX":"YABCDEFGHI"},"JKLMNOPQRS":null,"TUVWXYABCDEFGH":null,"IJKLMNOP":"QRST"}],"UVWXYABC":"DEFGH","IJKLMNOP":"QRSTUVWXY"},"ABCDEFGH":9,"IJKL":"MNOPQRST/UVWXYABCDE//FGHIJKLMNOPQRST!4UV2WXYABC7826D7659EF223GH40I91J","KLMNOPQRST":[{"UVWXYABCDEFG":null,"HIJKLMNO":0,"PQRS":"T","UVWX":{"YABC":{"DEFG":"HIJK/LMNO/PQRSTU","VWXYABCD":"EFGHIJKLM","NOPQRSTU":"VWXY"},"ABCDEFGH":"IJKLMNO","PQRSTUVW":"XYAB"},"CDEFGHIJ":"KLMNOPQR"}],"STUVWXYA":null,"BCDEFGH":null,"IJKLMN":null,"OPQRSTUVWXYABC":null,"DEFGHIJK":"LMNOPQRS"},{"TUVW":{"XYAB":[{"CDEFGHIJ":{"KLMN":"OPQRSTUV/WXYABCDEFG//HIJKLMNOPQRSTUV!4WX2YABCDE7826F7659GH223IJ40K91L","MNOPQRST":"UVWXYABCDE"},"FGHIJKLMNO":[{"PQRS":"T","UVWXYABC":"DEFGHIJKLM"}],"NOPQRSTUVWXYAB":null,"CDEFGHIJ":"KLMN"}],"OPQRSTUV":"WXYAB","CDEFGHIJ":"KLMNOPQRS"},"TUVWXYAB":9,"CDEF":"GHIJKLMN/OPQRSTUVWX//YABCDEFGHIJKLM!4NO2PQRSTU7826V7659WX223YA40B91C","DEFGHIJKLM":[{"NOPQRSTUVWXY":null,"ABCDEFGH":0,"IJKL":"M","NOPQ":{"RSTU":{"VWXY":"ABCD/EFGH/IJKLMN","OPQRSTUV":"WXYABCDEF","GHIJKLMN":"OPQR"},"STUVWXYA":"BCDEFGH","IJKLMNOP":"QRST"},"UVWXYABC":"DEFGHIJK"}],"LMNOPQRS":null,"TUVWXYA":null,"BCDEFG":null,"HIJKLMNOPQRSTU":null,"VWXYABCD":"EFGHIJKL"},{"MNOP":{"QRST":[{"UVWXYABC":0,"DEFG":["HIJK"],"LMNO":[{"PQRS":{"TUVW":"XYABCDEF/GHIJKLMNOP","QRSTUVWX":"YABCDEFGH","IJKLMNOP":"QRST"},"UVWXYABC":"DEFGHIJ","KLMNOPQR":"STUV"}],"WXYAB":[{"CDEF":{"GHIJ":{"KLMN":"OPQRSTUV/WXYABCDEFG","HIJKLMNO":"PQRSTUVWX","YABCDEFG":"HIJK"},"LMNOPQRS":"TUVWXYA","BCDEFGHI":"JKLM"},"NOPQRSTU":"VWX"}],"YABCDEFG":"HIJKLMNOPQR","STUVWXYA":"BCDEFGHIJ"},{"KLMNOPQR":"=","S":{"TUVWXYA":{"BCDE":"FGHI","JKLMNOPQ":"RSTUVWXYAB"},"CDEFGHIJ":"@KLMN/OPQR/STUVWX","YABCDEFG":"HIJKLM","NOPQRSTU":"VWXYABCDEF"},"G":{"HIJKLMNO":{"PQRS":"TUVW/XYAB/CDEFGH//IJKLMN!O41P8QR98S00T204U9800998VWX8427Y","ABCDEFGH":"IJKLMNOPQR"},"STUVWXYABC":null,"DEFGHIJKLMNOPQ":null,"RSTUVWXY":"ABCD"},"EFGHIJKL":"MNOPQR","STUVWXYA":"BCDEFGHIJK"},{"LMNOPQR":[{"STUV":"WXYA","BCDEFGHI":"JKLMNOPQRS"}],"TUVWXYAB":"CDEFGH","IJKLMNOP":"QRSTUVWXY"}],"ABCDEFGH":"IJKLM","NOPQRSTU":"VWXYABCDE"},"FGHIJKLM":37,"NOPQ":"RSTUVWXY/ABCDEFGHIJ//KLMNOPQRST!U41V8WX98Y00A204B9800998CDE8427F","GHIJKLMNOP":null,"QRSTUVWX":null,"YABCDEF":[{"GHIJKLMNOPQR":null,"STUVWXYA":0,"BCDE":"","FGHI":{"JKLM":{"NOPQ":"RSTUVWXY/ABCDEFGHIJ","KLMNOPQR":"STUVWXYAB","CDEFGHIJ":"KLMN"},"OPQRSTUV":"WXYABCD","EFGHIJKL":"MNOP"},"QRSTUVWX":"YABCDEFG"}],"HIJKLM":null,"NOPQRSTUVWXYAB":null,"CDEFGHIJ":"KLMNOPQR"}],"STUVWXYABC":null,"DEFGHIJK":[{"LMNO":{"PQRS":"TUVW/XYAB/CDEFGH","IJKLMNOP":"QRSTUVWXY","ABCDEFGH":"IJKL"},"MNOPQRST":"UVWXYAB","CDEFGHIJ":"KLMN"}],"OPQRSTUV":1,"WXYA":"BCDEFGHI/JKLMNOPQRS","TUVWXYAB":null,"CDEFGHIJKLMNOP":null,"QRSTUVWX":"YABCDE","FGHIJKLM":"NOPQ"}]}`)
expected := stdjson.Valid(data)
actual := json.Valid(data)
if expected != actual {
t.Fatalf("failed to valid: expected %v but got %v", expected, actual)
}
}
type example struct {
compact string
indent string