This commit replaces positional field initialization in test cases
with named field initialization to improve readability.
While at it, also remove tests that were commented out.
If the user provides a JSON-to-CBOR transcode function, a value whose type implements json.Marshaler
and not cbor.Marshaler will be encoded by first calling its MarshalJSON method, then transcoding the
result to CBOR.
Signed-off-by: Ben Luddy <bluddy@redhat.com>
This commit adds features related to allowing user to specify
a buffer rather than using built-in buffer pool:
- cbor.MarshalToBuffer() uses codec's default options to encode
to user provided buffer instead of using built-in buffer pool.
- UserBufferEncMode interface extends EncMode interface with
MarshalToBuffer() so user can provide buffer for encoding
instead of using built-in buffer pool.
- EncOptions.UserBufferEncMode() returns UserBufferEncMode
- EncOptions.UserBufferEncModeWithTags() returns UserBufferEncMode
- EncOptions.UserBufferEncModeWithSharedTags() returns UserBufferEncMode
By default, values whose type implements BinaryMarshaler encode to a byte string whose contents are
the result of calling MarshalBinary, and decoding a byte string into a BinaryUnmarshaler calls
UnmarshalBinary on the contents of the byte string. These options make it possible to disable both
behaviors.
Signed-off-by: Ben Luddy <bluddy@redhat.com>
These options improve interoperability with programs that use JSON to encode and decode objects to
and from both struct types and empty interface values.
Signed-off-by: Ben Luddy <bluddy@redhat.com>
The motivation is to prevent programs that consume the output from assuming (incorrectly) that it
was encoded deterministically, even when implementation details make the output apparently stable.
Signed-off-by: Ben Luddy <bluddy@redhat.com>
This commit checks Marshaler data for well-formedness
(and very limited partial validation) by reusing one
of four DecModes created during startup. These modes
are safe for parallel use by different Marshalers.
MarshalerError is returned if CBOR data item returned from
MarshalCBOR() fails either:
- well-formedness check, or
- tag validation for builtin tags 0-3
The StringType encode option supports use cases that must not produce invalid CBOR (even if
well-formed) and must be able to encode Go strings that do not contain valid UTF-8 sequences,
without the overhead of sanitizing all input Go values. The default value of the option is
TextStringType and encodes Go strings to CBOR major type 3, which is identical to the preexisting
behavior.
Signed-off-by: Ben Luddy <bluddy@redhat.com>
The current behavior in the library is to omits if field value
would encode as empty JSON value. This behavior is different from
the bahavior in golang encoding/json which omits if field value
is an empty Go value (defined as false, 0, a nil pointer, a nil
interface value, and any empty array, slice, map, or string).
The OmitEmptyMode = 1 is added to encoding option so that cbor
would decode omitempty fields similarly to encoding/json in go.
Signed-off-by: Vu Dinh <vudinh@outlook.com>
- Moved NilContainersMode from decode.go to encode.go
because it is only an encoding option.
- Renamed NullForNil to NilContainerAsNull.
- Renamed EmptyForNil to NilContainerAsEmpty.
- Updated and added some comments.
Add a SimpleValue type which is distinct from Go's numeric types.
Add support for properly encoding and decoding all simple values,
including 252 unassigned/reserved simple values.
Improve support for simple values as map keys by making them
distinct from uint64 values 0-255.
CBOR simple values are a subset of major type 7
that is not floating-point.
Only 4 simple values were previously supported by this codec:
- false
- true
- null
- undefined
The other 252 simple values are unassigned or reserved by IANA.
Struct field with "omitempty" option is omitted during encoding if:
- field is false
- field is 0
- field is empty string, array, slice, or map
- field is null pointer or interface
- field is nil or empty slice for cbor.RawMessage
- (new) field is nil or empty slice for types implementing cbor.BinaryMarshaler
- (new) field is empty struct
Currently "omitempty" option is a no-op for the following types:
- time.Time
- big.Int
- cbor.Tag
- cbor.RawTag
- types implementing cbor.Marshaler
Removed Go's copyright notice in encode.go.
Updated README and LICENSE to remove Go's copyright and license.
Closes#232
By default, encode big.Int value to CBOR integer (if value fits),
otherwise encode to CBOR bignum (CBOR tag 2 or 3).
BigIntConvert is the CBOR encoding option for big.Int:
- BigIntConvertShortest: (default) encode big.Int to CBOR integer
if value fits, otherwise encode to CBOR bignum.
- BigIntConvertNone: encode big.Int to CBOR bignum without
converting it to another CBOR type.
Decoder can decode the following to big.Int:
- CBOR bignum (tags 2 and 3)
- CBOR integers (major type 0 and 1)
When decoding CBOR bignum to empty interface, decode to big.Int.
When decoding CBOR negative integer (major type 1) to empty interface:
- if value fits int64, decode to int64.
- if value doesn't fit int64, decode to big.Int.
Closes#209
This CBOR library provides 2 options for duplicate map keys:
- DupMapKeyQuiet: Turn off detection of duplicate map keys. It tries
to use a "keep fastest" method by choosing either "keep first" or
"keep last" depending on the Go data type.
- DupMapKeyEnforcedAPF: Turn on detection and rejection of duplidate
map keys. Decoding stops immediately and returns DupMapKeyError when the
first duplicate key is detected. The error includes the duplicate map key
and the index number.
APF suffix means "Allow Partial Fill" so the destination map or struct
can contain some decoded values at the time of error. It is the caller's
responsibility to respond to the DuplicateMapKeyErr by discarding the
partially filled result if that's required by their protocol.
Detection of duplicate map keys relies on whether the CBOR map key would
be a duplicate "key" when decoded and applied to the user-provided Go map
or struct.
CBOR tag support includes:
- API to use TagSet to register user-defined Go type with CBOR tag number.
- API to encode Go value with CBOR tag number without registering.
- API to extract CBOR tag number with Tag or RawTag structs.
- API to use immutable TagSet or mutable shared TagSet (shared tag registry).
- EncOptions/DecOptions settings to tag or not tag time.Time values.
Improved decoding speed and memory for "keyasint" struct (COSE, CWT, etc.):
- speed is faster by 24% - 28%.
- mem allocs is reduced by 44% - 61%.
- mem bytes is reduced by 13% - 26%.
Encoding is a bit slower around 2% - 4% because of added features. Optimization
of encoding can be tackled in future releases because it is still very fast.
TagSet is a Go interface to register tag support for user-defined Go types.
EncMode and DecMode are reusable interfaces that are safe for concurrency.
They export codec functions with identical signatures to encoding/json.
EncMode can be created by these functions:
EncOptions{...}.EncMode()
EncOptions{...}.EncModeWithTags(TagSet)
EncOptions{...}.EncModeWithSharedTags(TagSet)
DecMode can be created by these functions:
DecOptions{...}.DecMode()
DecOptions{...}.DecModeWithTags(TagSet)
DecOptions{...}.DecModeWithSharedTags(TagSet)
Tag and RawTag are structs used to encode/decode CBOR tag number with tag content.
See docs and closed issues for more details.
Closed: #44Closed: #47Closed: #125Closed: #147Closed: #151
Implement v2.0 API for easier CBOR encoding/decoding. See issue #117 for summary.
Replaced EncOptions.TimeRFC3339 bool with TimeMode values:
* TimeUnix // secs, converted to smallest CBOR integer that fits
* TimeUnixMicro // μs, CBOR float with subsecs in fractional part
* TimeUnixDynamic // secs or μs, either int or float depending on empty subsecs
* TimeRFC3339 // secs, string
* TimeRFC3339Nano // ns, string with trailing zeros removed
Decode CBOR time NaN and Infinity values to Go's "zero time" value.
This is how CBOR Null values are decoded to time.Time.
Removed deprecated options (Canonical & CTAP2Canoical) in EncOptions.
Removed Valid() function.
Improved performance and memory alloc by
* using pointer receivers for types implementing sort.Interface and others.
* storing pointer in sync.Pool.
* storing pointer as map value in sync.Map.
Used roughly 20 linters and resolved many reported issues.
Switched to GitHub Actions for CI to lint, test, and check code coverage.
Extensive improvements to README.md.
Thanks @x448 for API design ideas, travis & github ci configs, filing issues,
and improving README.md.
Closes: #107Closes: #119Closes: #120Closes: #123Closes: #124Closes: #127