Skip to content

Commit

Permalink
Merge pull request #5 from jrapoport/escape-seq-support
Browse files Browse the repository at this point in the history
Escape sequence support for sparse encrypted structs
  • Loading branch information
jrapoport authored Oct 27, 2024
2 parents 750fa4e + cc795ae commit 953a7bc
Show file tree
Hide file tree
Showing 16 changed files with 1,724 additions and 1,181 deletions.
20 changes: 10 additions & 10 deletions encoding/json/encoders/lookup/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Decoder struct {
log log.Logger
}

// NewLookupDecoder returns an decoder that reads a lookup table. It will check the
// NewLookupDecoder returns a decoder that reads a lookup table. It will check the
// iterated string values to see if they match our lookup token. If there is a match,
// it will replace it with a decoded value from the lookup table or an empty value.
func NewLookupDecoder(ctx *Context, typ reflect2.Type, decoder jsoniter.ValDecoder) jsoniter.ValDecoder {
Expand Down Expand Up @@ -76,7 +76,7 @@ func (d *Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
d.decoder.Decode(ptr, iter)
return
}
// get the from type
// get the 'from' type
fromType := iter.WhatIsNext()
// secure tokens will be type string. if this is not
// a string, call the default decoder and bail.
Expand All @@ -85,23 +85,23 @@ func (d *Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
d.decoder.Decode(ptr, iter)
return
}
// read the string & for mat a key
key := Key(iter.ReadString())
// read the string & format a key
val := iter.ReadRawString()
key := Key(val)
// check to see if it is one of ours
if !key.IsTokenKey(d.token) {
// we use an Iterator avoid setting the ptr directly since it might be a string
// or an interface or who knows what. this was the codecs handle it for us.
subIter := iter.Pool().BorrowIterator([]byte(fmt.Sprintf(`"%s"`, key)))
subIter := iter.Pool().BorrowIterator([]byte(`"` + key + `"`))
defer iter.Pool().ReturnIterator(subIter)
d.log.Debugf("decode string: %s", key)
// decode the string
d.log.Debugf("decode value: %s", val)
d.decoder.Decode(ptr, subIter)
return
}
// we have a valid lookup key. look it up in our table
val, err := d.lookupKey(key)
ent, err := d.lookupKey(key)
// did we find something in the lookup table?
if err != nil || val == nil {
if err != nil || ent == nil {
d.log.Debugf("lookup entry not found: %s", key)
// this is expected when sparse decoding a struct.
if d.valType.Kind() == reflect.Interface {
Expand All @@ -113,7 +113,7 @@ func (d *Decoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
}
// clear the buffer
d.stream.Reset(nil)
val.WriteTo(d.stream)
ent.WriteTo(d.stream)
subIter := iter.Pool().BorrowIterator(d.stream.Buffer())
defer iter.Pool().ReturnIterator(subIter)
// decode the string
Expand Down
5 changes: 5 additions & 0 deletions encoding/json/encoders/lookup/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ func TestLookupDecoder_Decode(t *testing.T) {
`"tst0xtesting%d_22"`,
`{"Value":"a-struct-ptr-value"}`,
},
{
&testObject{"a\nstruct\tptr\"value"},
`"tst0xtesting%d_22"`,
`{"Value":"a\nstruct\tptr\"value"}`,
},
}
lookUpTable := "{"
for i, test := range tests {
Expand Down
5 changes: 5 additions & 0 deletions encoding/json/encoders/lookup/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func TestLookupEncoder_Encode(t *testing.T) {
`"tst0xtesting%d_22"`,
`{"Value":"a-struct-ptr-value"}`,
},
{
&testObject{"a\nstruct\tptr\"value"},
`"tst0xtesting%d_22"`,
`{"Value":"a\nstruct\tptr\"value"}`,
},
}
encoded := ""
lookup := ""
Expand Down
6 changes: 5 additions & 1 deletion encoding/json/encoders/secure/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ var decoderTests = []decoderTest{
{jsonSealed, jsonUnsealed, &JSON{}, jsonDecoded, jsonMap, sparseOpt},
{jsonComp, jsonUnsealed, &JSON{}, jsonDecoded, jsonMap, noOpt},
{jsonComp, jsonUnsealed, &JSON{}, jsonDecoded, jsonMap, sparseOpt},
{ctrlSealed, ctrlUnsealed, &Escape{}, ctrlDecoded, ctrlMap, noOpt},
{ctrlSealed, ctrlUnsealed, &Escape{}, ctrlSparse, ctrlMapSparse, sparseOpt},
{ctrlComp, ctrlUnsealed, &Escape{}, ctrlDecoded, ctrlMap, noOpt},
{ctrlComp, ctrlUnsealed, &Escape{}, ctrlSparse, ctrlMapSparse, sparseOpt},
{hashSealed, hashUnsealed, &Hash{}, hashDecoded, hashMap, noOpt},
{hashSealed, hashUnsealed, &Hash{}, hashDecoded, hashMap, sparseOpt},
{hashComp, hashUnsealed, &Hash{}, hashDecoded, hashMap, noOpt},
Expand All @@ -49,7 +53,7 @@ var decoderTests = []decoderTest{
func TestSecureDecoderExtension(t *testing.T) {
for _, test := range decoderTests {
testName := reflect.TypeOf(test.dst).Elem().Name()
if test.sparse != nil {
if test.sparse != noOpt {
testName += " sparse"
}
t.Run(testName, func(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions encoding/json/encoders/secure/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ var encoderTests = []encoderTest{
{noneObj, noneEncoded, noneComp, compOpt},
{jsonObj, jsonEncoded, jsonSealed, noOpt},
{jsonObj, jsonEncoded, jsonComp, compOpt},
{ctrlObj, ctrlEncoded, ctrlSealed, noOpt},
{ctrlObj, ctrlEncoded, ctrlComp, compOpt},
{hashObj, hashEncoded, hashSealed, noOpt},
{hashObj, hashEncoded, hashComp, compOpt},
{secObj, secEncoded, secSealed, noOpt},
Expand Down
12 changes: 6 additions & 6 deletions encoding/json/encoders/secure/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func newFuncOption(f func(*Options)) *funcOption {
}
}

// applyOptions accepts a Options struct and applies the Option(s) to it.
// applyOptions accepts an Options struct and applies the Option(s) to it.
func applyOptions(opts Options, opt ...Option) Options {
if opt != nil {
for _, o := range opt {
Expand All @@ -64,29 +64,29 @@ func applyOptions(opts Options, opt ...Option) Options {
return opts
}

// SparseDecode returns a Option that set the decoder to return sparsely
// SparseDecode returns an Option that set the decoder to return sparsely
// decoded data. If the JSON data was not sparely encoded, this does nothing.
func SparseDecode() Option {
return newFuncOption(func(o *Options) {
o.sparse = true
})
}

// WithCompressor returns a Option that compresses data.
// WithCompressor returns an Option that compresses data.
func WithCompressor(compressor compress.CompressorFunc) Option {
return newFuncOption(func(o *Options) {
o.compressor = compressor
})
}

// WithDecompressor returns a Option that decompresses data.
// WithDecompressor returns an Option that decompresses data.
func WithDecompressor(decompressor compress.DecompressorFunc) Option {
return newFuncOption(func(o *Options) {
o.decompressor = decompressor
})
}

// WithCompression returns a Option that compresses & decompresses data with Zstd.
// WithCompression returns an Option that compresses & decompresses data with Zstd.
func WithCompression(format compress.Format) Option {
return newFuncOption(func(o *Options) {
switch format {
Expand All @@ -99,7 +99,7 @@ func WithCompression(format compress.Format) Option {
})
}

// WithLogger returns a Option which sets the logger for the extension.
// WithLogger returns an Option which sets the logger for the extension.
func WithLogger(l log.Logger) Option {
return newFuncOption(func(o *Options) {
o.log = l
Expand Down
6 changes: 4 additions & 2 deletions encoding/json/encoders/secure/secure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ var tests = []testCase{
{noneObj, &None{}, noneDecoded, noneMap, sparseOpt},
{jsonObj, &JSON{}, jsonDecoded, jsonMap, noOpt},
{jsonObj, &JSON{}, jsonDecoded, jsonMap, sparseOpt},
{ctrlObj, &Escape{}, ctrlDecoded, ctrlMap, noOpt},
{ctrlObj, &Escape{}, ctrlSparse, ctrlMapSparse, sparseOpt},
{hashObj, &Hash{}, hashDecoded, hashMap, noOpt},
{hashObj, &Hash{}, hashDecoded, hashMap, sparseOpt},
{secObj, &Secure{}, secDecoded, secMap, noOpt},
Expand All @@ -47,10 +49,10 @@ func TestSecureExtension(t *testing.T) {
for _, compressed := range comps {
for _, test := range tests {
testName := reflect.TypeOf(test.dst).Elem().Name()
if test.sparse != nil {
if test.sparse != noOpt {
testName += " sparse"
}
if compressed != nil {
if compressed != noOpt {
testName += " compressed"
}
t.Run(testName, func(t *testing.T) {
Expand Down
Loading

0 comments on commit 953a7bc

Please sign in to comment.