Binary format support (#37)
Adds support for binary logging (with cbor encoding) in addition to JSON. Use the binary_log compile tag to enable the feature.
This commit is contained in:
parent
3ab376bc30
commit
ddfae1b613
|
@ -9,4 +9,5 @@ matrix:
|
|||
allow_failures:
|
||||
- go: "master"
|
||||
script:
|
||||
go test -v -race -cpu=1,2,4 -bench . -benchmem ./...
|
||||
- go test -v -race -cpu=1,2,4 -bench . -benchmem ./...
|
||||
- go test -v -tags binary_log -race -cpu=1,2,4 -bench . -benchmem ./...
|
||||
|
|
60
array.go
60
array.go
|
@ -3,8 +3,6 @@ package zerolog
|
|||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
var arrayPool = &sync.Pool{
|
||||
|
@ -15,6 +13,8 @@ var arrayPool = &sync.Pool{
|
|||
},
|
||||
}
|
||||
|
||||
// Array is used to prepopulate an array of items
|
||||
// which can be re-used to add to log messages.
|
||||
type Array struct {
|
||||
buf []byte
|
||||
}
|
||||
|
@ -26,16 +26,17 @@ func Arr() *Array {
|
|||
return a
|
||||
}
|
||||
|
||||
// MarshalZerologArray method here is no-op - since data is
|
||||
// already in the needed format.
|
||||
func (*Array) MarshalZerologArray(*Array) {
|
||||
}
|
||||
|
||||
func (a *Array) write(dst []byte) []byte {
|
||||
if len(a.buf) == 0 {
|
||||
dst = append(dst, `[]`...)
|
||||
} else {
|
||||
a.buf[0] = '['
|
||||
dst = append(append(dst, a.buf...), ']')
|
||||
dst = appendArrayStart(dst)
|
||||
if len(a.buf) > 0 {
|
||||
dst = append(append(dst, a.buf...))
|
||||
}
|
||||
dst = appendArrayEnd(dst)
|
||||
arrayPool.Put(a)
|
||||
return dst
|
||||
}
|
||||
|
@ -43,126 +44,125 @@ func (a *Array) write(dst []byte) []byte {
|
|||
// Object marshals an object that implement the LogObjectMarshaler
|
||||
// interface and append it to the array.
|
||||
func (a *Array) Object(obj LogObjectMarshaler) *Array {
|
||||
a.buf = append(a.buf, ',')
|
||||
e := Dict()
|
||||
obj.MarshalZerologObject(e)
|
||||
e.buf = append(e.buf, '}')
|
||||
a.buf = append(a.buf, e.buf...)
|
||||
e.buf = appendEndMarker(e.buf)
|
||||
a.buf = append(appendArrayDelim(a.buf), e.buf...)
|
||||
eventPool.Put(e)
|
||||
return a
|
||||
}
|
||||
|
||||
// Str append the val as a string to the array.
|
||||
func (a *Array) Str(val string) *Array {
|
||||
a.buf = json.AppendString(append(a.buf, ','), val)
|
||||
a.buf = appendString(appendArrayDelim(a.buf), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bytes append the val as a string to the array.
|
||||
func (a *Array) Bytes(val []byte) *Array {
|
||||
a.buf = json.AppendBytes(append(a.buf, ','), val)
|
||||
a.buf = appendBytes(appendArrayDelim(a.buf), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Hex append the val as a hex string to the array.
|
||||
func (a *Array) Hex(val []byte) *Array {
|
||||
a.buf = json.AppendHex(append(a.buf, ','), val)
|
||||
a.buf = appendHex(appendArrayDelim(a.buf), val)
|
||||
return a
|
||||
}
|
||||
|
||||
// Err append the err as a string to the array.
|
||||
func (a *Array) Err(err error) *Array {
|
||||
a.buf = json.AppendError(append(a.buf, ','), err)
|
||||
a.buf = appendError(appendArrayDelim(a.buf), err)
|
||||
return a
|
||||
}
|
||||
|
||||
// Bool append the val as a bool to the array.
|
||||
func (a *Array) Bool(b bool) *Array {
|
||||
a.buf = json.AppendBool(append(a.buf, ','), b)
|
||||
a.buf = appendBool(appendArrayDelim(a.buf), b)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int append i as a int to the array.
|
||||
func (a *Array) Int(i int) *Array {
|
||||
a.buf = json.AppendInt(append(a.buf, ','), i)
|
||||
a.buf = appendInt(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int8 append i as a int8 to the array.
|
||||
func (a *Array) Int8(i int8) *Array {
|
||||
a.buf = json.AppendInt8(append(a.buf, ','), i)
|
||||
a.buf = appendInt8(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int16 append i as a int16 to the array.
|
||||
func (a *Array) Int16(i int16) *Array {
|
||||
a.buf = json.AppendInt16(append(a.buf, ','), i)
|
||||
a.buf = appendInt16(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int32 append i as a int32 to the array.
|
||||
func (a *Array) Int32(i int32) *Array {
|
||||
a.buf = json.AppendInt32(append(a.buf, ','), i)
|
||||
a.buf = appendInt32(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Int64 append i as a int64 to the array.
|
||||
func (a *Array) Int64(i int64) *Array {
|
||||
a.buf = json.AppendInt64(append(a.buf, ','), i)
|
||||
a.buf = appendInt64(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint append i as a uint to the array.
|
||||
func (a *Array) Uint(i uint) *Array {
|
||||
a.buf = json.AppendUint(append(a.buf, ','), i)
|
||||
a.buf = appendUint(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint8 append i as a uint8 to the array.
|
||||
func (a *Array) Uint8(i uint8) *Array {
|
||||
a.buf = json.AppendUint8(append(a.buf, ','), i)
|
||||
a.buf = appendUint8(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint16 append i as a uint16 to the array.
|
||||
func (a *Array) Uint16(i uint16) *Array {
|
||||
a.buf = json.AppendUint16(append(a.buf, ','), i)
|
||||
a.buf = appendUint16(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint32 append i as a uint32 to the array.
|
||||
func (a *Array) Uint32(i uint32) *Array {
|
||||
a.buf = json.AppendUint32(append(a.buf, ','), i)
|
||||
a.buf = appendUint32(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Uint64 append i as a uint64 to the array.
|
||||
func (a *Array) Uint64(i uint64) *Array {
|
||||
a.buf = json.AppendUint64(append(a.buf, ','), i)
|
||||
a.buf = appendUint64(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float32 append f as a float32 to the array.
|
||||
func (a *Array) Float32(f float32) *Array {
|
||||
a.buf = json.AppendFloat32(append(a.buf, ','), f)
|
||||
a.buf = appendFloat32(appendArrayDelim(a.buf), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Float64 append f as a float64 to the array.
|
||||
func (a *Array) Float64(f float64) *Array {
|
||||
a.buf = json.AppendFloat64(append(a.buf, ','), f)
|
||||
a.buf = appendFloat64(appendArrayDelim(a.buf), f)
|
||||
return a
|
||||
}
|
||||
|
||||
// Time append t formated as string using zerolog.TimeFieldFormat.
|
||||
func (a *Array) Time(t time.Time) *Array {
|
||||
a.buf = json.AppendTime(append(a.buf, ','), t, TimeFieldFormat)
|
||||
a.buf = appendTime(appendArrayDelim(a.buf), t, TimeFieldFormat)
|
||||
return a
|
||||
}
|
||||
|
||||
// Dur append d to the array.
|
||||
func (a *Array) Dur(d time.Duration) *Array {
|
||||
a.buf = json.AppendDuration(append(a.buf, ','), d, DurationFieldUnit, DurationFieldInteger)
|
||||
a.buf = appendDuration(appendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return a
|
||||
}
|
||||
|
||||
|
@ -171,6 +171,6 @@ func (a *Array) Interface(i interface{}) *Array {
|
|||
if obj, ok := i.(LogObjectMarshaler); ok {
|
||||
return a.Object(obj)
|
||||
}
|
||||
a.buf = json.AppendInterface(append(a.buf, ','), i)
|
||||
a.buf = appendInterface(appendArrayDelim(a.buf), i)
|
||||
return a
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func TestArray(t *testing.T) {
|
|||
Time(time.Time{}).
|
||||
Dur(0)
|
||||
want := `[true,1,2,3,4,5,6,7,8,9,10,11,12,"a","b","1f","0001-01-01T00:00:00Z",0]`
|
||||
if got := string(a.write([]byte{})); got != want {
|
||||
if got := decodeObjectToStr(a.write([]byte{})); got != want {
|
||||
t.Errorf("Array.write()\ngot: %s\nwant: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,453 @@
|
|||
// +build binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
// "io/ioutil"
|
||||
stdlog "log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ExampleBinaryNew() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"info","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_With() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).
|
||||
With().
|
||||
Str("foo", "bar").
|
||||
Logger()
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
|
||||
// Output: {"level":"info","foo":"bar","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Level() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).Level(WarnLevel)
|
||||
|
||||
log.Info().Msg("filtered out message")
|
||||
log.Error().Msg("kept message")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"error","message":"kept message"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Sample() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).Sample(&BasicSampler{N: 2})
|
||||
|
||||
log.Info().Msg("message 1")
|
||||
log.Info().Msg("message 2")
|
||||
log.Info().Msg("message 3")
|
||||
log.Info().Msg("message 4")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"info","message":"message 2"}
|
||||
// {"level":"info","message":"message 4"}
|
||||
}
|
||||
|
||||
type LevelNameHook1 struct{}
|
||||
|
||||
func (h LevelNameHook1) Run(e *Event, l Level, msg string) {
|
||||
if l != NoLevel {
|
||||
e.Str("level_name", l.String())
|
||||
} else {
|
||||
e.Str("level_name", "NoLevel")
|
||||
}
|
||||
}
|
||||
|
||||
type MessageHook string
|
||||
|
||||
func (h MessageHook) Run(e *Event, l Level, msg string) {
|
||||
e.Str("the_message", msg)
|
||||
}
|
||||
|
||||
func ExampleLogger_Hook() {
|
||||
var levelNameHook LevelNameHook1
|
||||
var messageHook MessageHook = "The message"
|
||||
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).Hook(levelNameHook).Hook(messageHook)
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"info","level_name":"info","the_message":"hello world","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Print() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Print("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"debug","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Printf() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Printf("hello %s", "world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"debug","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Debug() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Debug().
|
||||
Str("foo", "bar").
|
||||
Int("n", 123).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"debug","foo":"bar","n":123,"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Info() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Info().
|
||||
Str("foo", "bar").
|
||||
Int("n", 123).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"info","foo":"bar","n":123,"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Warn() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Warn().
|
||||
Str("foo", "bar").
|
||||
Msg("a warning message")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"warn","foo":"bar","message":"a warning message"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Error() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Error().
|
||||
Err(errors.New("some error")).
|
||||
Msg("error doing something")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"error","error":"some error","message":"error doing something"}
|
||||
}
|
||||
|
||||
func ExampleLogger_WithLevel() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.WithLevel(InfoLevel).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"level":"info","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Write() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).With().
|
||||
Str("foo", "bar").
|
||||
Logger()
|
||||
|
||||
stdlog.SetFlags(0)
|
||||
stdlog.SetOutput(log)
|
||||
|
||||
stdlog.Print("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleLogger_Log() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Str("bar", "baz").
|
||||
Msg("")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","bar":"baz"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Dict() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Dict("dict", Dict().
|
||||
Str("bar", "baz").
|
||||
Int("n", 1),
|
||||
).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","dict":{"bar":"baz","n":1},"message":"hello world"}
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Age int
|
||||
Created time.Time
|
||||
}
|
||||
|
||||
func (u User) MarshalZerologObject(e *Event) {
|
||||
e.Str("name", u.Name).
|
||||
Int("age", u.Age).
|
||||
Time("created", u.Created)
|
||||
}
|
||||
|
||||
type Users []User
|
||||
|
||||
func (uu Users) MarshalZerologArray(a *Array) {
|
||||
for _, u := range uu {
|
||||
a.Object(u)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleEvent_Array() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Array("array", Arr().
|
||||
Str("baz").
|
||||
Int(1),
|
||||
).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","array":["baz",1],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Array_object() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
// Users implements LogArrayMarshaler
|
||||
u := Users{
|
||||
User{"John", 35, time.Time{}},
|
||||
User{"Bob", 55, time.Time{}},
|
||||
}
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Array("users", u).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","users":[{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},{"name":"Bob","age":55,"created":"0001-01-01T00:00:00Z"}],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Object() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
// User implements LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Object("user", u).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","user":{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Interface() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
obj := struct {
|
||||
Name string `json:"name"`
|
||||
}{
|
||||
Name: "john",
|
||||
}
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Interface("obj", obj).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","obj":{"name":"john"},"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Dur() {
|
||||
d := time.Duration(10 * time.Second)
|
||||
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Dur("dur", d).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","dur":10000,"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Durs() {
|
||||
d := []time.Duration{
|
||||
time.Duration(10 * time.Second),
|
||||
time.Duration(20 * time.Second),
|
||||
}
|
||||
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst)
|
||||
|
||||
log.Log().
|
||||
Str("foo", "bar").
|
||||
Durs("durs", d).
|
||||
Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","durs":[10000,20000],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Dict() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).With().
|
||||
Str("foo", "bar").
|
||||
Dict("dict", Dict().
|
||||
Str("bar", "baz").
|
||||
Int("n", 1),
|
||||
).Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","dict":{"bar":"baz","n":1},"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Array() {
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).With().
|
||||
Str("foo", "bar").
|
||||
Array("array", Arr().
|
||||
Str("baz").
|
||||
Int(1),
|
||||
).Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","array":["baz",1],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Array_object() {
|
||||
// Users implements LogArrayMarshaler
|
||||
u := Users{
|
||||
User{"John", 35, time.Time{}},
|
||||
User{"Bob", 55, time.Time{}},
|
||||
}
|
||||
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).With().
|
||||
Str("foo", "bar").
|
||||
Array("users", u).
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","users":[{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},{"name":"Bob","age":55,"created":"0001-01-01T00:00:00Z"}],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Object() {
|
||||
// User implements LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).With().
|
||||
Str("foo", "bar").
|
||||
Object("user", u).
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","user":{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Interface() {
|
||||
obj := struct {
|
||||
Name string `json:"name"`
|
||||
}{
|
||||
Name: "john",
|
||||
}
|
||||
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).With().
|
||||
Str("foo", "bar").
|
||||
Interface("obj", obj).
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","obj":{"name":"john"},"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Dur() {
|
||||
d := time.Duration(10 * time.Second)
|
||||
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).With().
|
||||
Str("foo", "bar").
|
||||
Dur("dur", d).
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","dur":10000,"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_Durs() {
|
||||
d := []time.Duration{
|
||||
time.Duration(10 * time.Second),
|
||||
time.Duration(20 * time.Second),
|
||||
}
|
||||
|
||||
dst := bytes.Buffer{}
|
||||
log := New(&dst).With().
|
||||
Str("foo", "bar").
|
||||
Durs("durs", d).
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
fmt.Println(decodeIfBinaryToString(dst.Bytes()))
|
||||
// Output: {"foo":"bar","durs":[10000,20000],"message":"hello world"}
|
||||
}
|
|
@ -39,6 +39,7 @@ type ConsoleWriter struct {
|
|||
|
||||
func (w ConsoleWriter) Write(p []byte) (n int, err error) {
|
||||
var event map[string]interface{}
|
||||
p = decodeIfBinaryToBytes(p)
|
||||
err = json.Unmarshal(p, &event)
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package zerolog_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
func ExampleConsoleWriter_Write() {
|
||||
log := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true})
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
// Output: <nil> |INFO| hello world
|
||||
}
|
89
context.go
89
context.go
|
@ -3,8 +3,6 @@ package zerolog
|
|||
import (
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
// Context configures a new sub-logger with contextual fields.
|
||||
|
@ -25,8 +23,8 @@ func (c Context) Fields(fields map[string]interface{}) Context {
|
|||
|
||||
// Dict adds the field key with the dict to the logger context.
|
||||
func (c Context) Dict(key string, dict *Event) Context {
|
||||
dict.buf = append(dict.buf, '}')
|
||||
c.l.context = append(json.AppendKey(c.l.context, key), dict.buf...)
|
||||
dict.buf = appendEndMarker(dict.buf)
|
||||
c.l.context = append(appendKey(c.l.context, key), dict.buf...)
|
||||
eventPool.Put(dict)
|
||||
return c
|
||||
}
|
||||
|
@ -35,7 +33,7 @@ func (c Context) Dict(key string, dict *Event) Context {
|
|||
// Use zerolog.Arr() to create the array or pass a type that
|
||||
// implement the LogArrayMarshaler interface.
|
||||
func (c Context) Array(key string, arr LogArrayMarshaler) Context {
|
||||
c.l.context = json.AppendKey(c.l.context, key)
|
||||
c.l.context = appendKey(c.l.context, key)
|
||||
if arr, ok := arr.(*Array); ok {
|
||||
c.l.context = arr.write(c.l.context)
|
||||
return c
|
||||
|
@ -55,33 +53,32 @@ func (c Context) Array(key string, arr LogArrayMarshaler) Context {
|
|||
func (c Context) Object(key string, obj LogObjectMarshaler) Context {
|
||||
e := newEvent(levelWriterAdapter{ioutil.Discard}, 0, true)
|
||||
e.Object(key, obj)
|
||||
e.buf[0] = ',' // A new event starts as an object, we want to embed it.
|
||||
c.l.context = append(c.l.context, e.buf...)
|
||||
c.l.context = appendObjectData(c.l.context, e.buf)
|
||||
eventPool.Put(e)
|
||||
return c
|
||||
}
|
||||
|
||||
// Str adds the field key with val as a string to the logger context.
|
||||
func (c Context) Str(key, val string) Context {
|
||||
c.l.context = json.AppendString(json.AppendKey(c.l.context, key), val)
|
||||
c.l.context = appendString(appendKey(c.l.context, key), val)
|
||||
return c
|
||||
}
|
||||
|
||||
// Strs adds the field key with val as a string to the logger context.
|
||||
func (c Context) Strs(key string, vals []string) Context {
|
||||
c.l.context = json.AppendStrings(json.AppendKey(c.l.context, key), vals)
|
||||
c.l.context = appendStrings(appendKey(c.l.context, key), vals)
|
||||
return c
|
||||
}
|
||||
|
||||
// Bytes adds the field key with val as a []byte to the logger context.
|
||||
func (c Context) Bytes(key string, val []byte) Context {
|
||||
c.l.context = json.AppendBytes(json.AppendKey(c.l.context, key), val)
|
||||
c.l.context = appendBytes(appendKey(c.l.context, key), val)
|
||||
return c
|
||||
}
|
||||
|
||||
// Hex adds the field key with val as a hex string to the logger context.
|
||||
func (c Context) Hex(key string, val []byte) Context {
|
||||
c.l.context = json.AppendHex(json.AppendKey(c.l.context, key), val)
|
||||
c.l.context = appendHex(appendKey(c.l.context, key), val)
|
||||
return c
|
||||
}
|
||||
|
||||
|
@ -90,21 +87,21 @@ func (c Context) Hex(key string, val []byte) Context {
|
|||
// No sanity check is performed on b; it must not contain carriage returns and
|
||||
// be valid JSON.
|
||||
func (c Context) RawJSON(key string, b []byte) Context {
|
||||
c.l.context = append(json.AppendKey(c.l.context, key), b...)
|
||||
c.l.context = appendJSON(appendKey(c.l.context, key), b)
|
||||
return c
|
||||
}
|
||||
|
||||
// AnErr adds the field key with err as a string to the logger context.
|
||||
func (c Context) AnErr(key string, err error) Context {
|
||||
if err != nil {
|
||||
c.l.context = json.AppendError(json.AppendKey(c.l.context, key), err)
|
||||
c.l.context = appendError(appendKey(c.l.context, key), err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Errs adds the field key with errs as an array of strings to the logger context.
|
||||
func (c Context) Errs(key string, errs []error) Context {
|
||||
c.l.context = json.AppendErrors(json.AppendKey(c.l.context, key), errs)
|
||||
c.l.context = appendErrors(appendKey(c.l.context, key), errs)
|
||||
return c
|
||||
}
|
||||
|
||||
|
@ -112,164 +109,164 @@ func (c Context) Errs(key string, errs []error) Context {
|
|||
// To customize the key name, change zerolog.ErrorFieldName.
|
||||
func (c Context) Err(err error) Context {
|
||||
if err != nil {
|
||||
c.l.context = json.AppendError(json.AppendKey(c.l.context, ErrorFieldName), err)
|
||||
c.l.context = appendError(appendKey(c.l.context, ErrorFieldName), err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Bool adds the field key with val as a bool to the logger context.
|
||||
func (c Context) Bool(key string, b bool) Context {
|
||||
c.l.context = json.AppendBool(json.AppendKey(c.l.context, key), b)
|
||||
c.l.context = appendBool(appendKey(c.l.context, key), b)
|
||||
return c
|
||||
}
|
||||
|
||||
// Bools adds the field key with val as a []bool to the logger context.
|
||||
func (c Context) Bools(key string, b []bool) Context {
|
||||
c.l.context = json.AppendBools(json.AppendKey(c.l.context, key), b)
|
||||
c.l.context = appendBools(appendKey(c.l.context, key), b)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int adds the field key with i as a int to the logger context.
|
||||
func (c Context) Int(key string, i int) Context {
|
||||
c.l.context = json.AppendInt(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInt(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints adds the field key with i as a []int to the logger context.
|
||||
func (c Context) Ints(key string, i []int) Context {
|
||||
c.l.context = json.AppendInts(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInts(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int8 adds the field key with i as a int8 to the logger context.
|
||||
func (c Context) Int8(key string, i int8) Context {
|
||||
c.l.context = json.AppendInt8(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInt8(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints8 adds the field key with i as a []int8 to the logger context.
|
||||
func (c Context) Ints8(key string, i []int8) Context {
|
||||
c.l.context = json.AppendInts8(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInts8(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int16 adds the field key with i as a int16 to the logger context.
|
||||
func (c Context) Int16(key string, i int16) Context {
|
||||
c.l.context = json.AppendInt16(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInt16(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints16 adds the field key with i as a []int16 to the logger context.
|
||||
func (c Context) Ints16(key string, i []int16) Context {
|
||||
c.l.context = json.AppendInts16(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInts16(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int32 adds the field key with i as a int32 to the logger context.
|
||||
func (c Context) Int32(key string, i int32) Context {
|
||||
c.l.context = json.AppendInt32(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInt32(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints32 adds the field key with i as a []int32 to the logger context.
|
||||
func (c Context) Ints32(key string, i []int32) Context {
|
||||
c.l.context = json.AppendInts32(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInts32(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Int64 adds the field key with i as a int64 to the logger context.
|
||||
func (c Context) Int64(key string, i int64) Context {
|
||||
c.l.context = json.AppendInt64(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInt64(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Ints64 adds the field key with i as a []int64 to the logger context.
|
||||
func (c Context) Ints64(key string, i []int64) Context {
|
||||
c.l.context = json.AppendInts64(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInts64(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint adds the field key with i as a uint to the logger context.
|
||||
func (c Context) Uint(key string, i uint) Context {
|
||||
c.l.context = json.AppendUint(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUint(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints adds the field key with i as a []uint to the logger context.
|
||||
func (c Context) Uints(key string, i []uint) Context {
|
||||
c.l.context = json.AppendUints(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUints(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint8 adds the field key with i as a uint8 to the logger context.
|
||||
func (c Context) Uint8(key string, i uint8) Context {
|
||||
c.l.context = json.AppendUint8(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUint8(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints8 adds the field key with i as a []uint8 to the logger context.
|
||||
func (c Context) Uints8(key string, i []uint8) Context {
|
||||
c.l.context = json.AppendUints8(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUints8(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint16 adds the field key with i as a uint16 to the logger context.
|
||||
func (c Context) Uint16(key string, i uint16) Context {
|
||||
c.l.context = json.AppendUint16(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUint16(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints16 adds the field key with i as a []uint16 to the logger context.
|
||||
func (c Context) Uints16(key string, i []uint16) Context {
|
||||
c.l.context = json.AppendUints16(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUints16(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint32 adds the field key with i as a uint32 to the logger context.
|
||||
func (c Context) Uint32(key string, i uint32) Context {
|
||||
c.l.context = json.AppendUint32(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUint32(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints32 adds the field key with i as a []uint32 to the logger context.
|
||||
func (c Context) Uints32(key string, i []uint32) Context {
|
||||
c.l.context = json.AppendUints32(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUints32(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uint64 adds the field key with i as a uint64 to the logger context.
|
||||
func (c Context) Uint64(key string, i uint64) Context {
|
||||
c.l.context = json.AppendUint64(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUint64(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Uints64 adds the field key with i as a []uint64 to the logger context.
|
||||
func (c Context) Uints64(key string, i []uint64) Context {
|
||||
c.l.context = json.AppendUints64(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendUints64(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
// Float32 adds the field key with f as a float32 to the logger context.
|
||||
func (c Context) Float32(key string, f float32) Context {
|
||||
c.l.context = json.AppendFloat32(json.AppendKey(c.l.context, key), f)
|
||||
c.l.context = appendFloat32(appendKey(c.l.context, key), f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Floats32 adds the field key with f as a []float32 to the logger context.
|
||||
func (c Context) Floats32(key string, f []float32) Context {
|
||||
c.l.context = json.AppendFloats32(json.AppendKey(c.l.context, key), f)
|
||||
c.l.context = appendFloats32(appendKey(c.l.context, key), f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Float64 adds the field key with f as a float64 to the logger context.
|
||||
func (c Context) Float64(key string, f float64) Context {
|
||||
c.l.context = json.AppendFloat64(json.AppendKey(c.l.context, key), f)
|
||||
c.l.context = appendFloat64(appendKey(c.l.context, key), f)
|
||||
return c
|
||||
}
|
||||
|
||||
// Floats64 adds the field key with f as a []float64 to the logger context.
|
||||
func (c Context) Floats64(key string, f []float64) Context {
|
||||
c.l.context = json.AppendFloats64(json.AppendKey(c.l.context, key), f)
|
||||
c.l.context = appendFloats64(appendKey(c.l.context, key), f)
|
||||
return c
|
||||
}
|
||||
|
||||
|
@ -292,31 +289,31 @@ func (c Context) Timestamp() Context {
|
|||
|
||||
// Time adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||
func (c Context) Time(key string, t time.Time) Context {
|
||||
c.l.context = json.AppendTime(json.AppendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
c.l.context = appendTime(appendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
return c
|
||||
}
|
||||
|
||||
// Times adds the field key with t formated as string using zerolog.TimeFieldFormat.
|
||||
func (c Context) Times(key string, t []time.Time) Context {
|
||||
c.l.context = json.AppendTimes(json.AppendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
c.l.context = appendTimes(appendKey(c.l.context, key), t, TimeFieldFormat)
|
||||
return c
|
||||
}
|
||||
|
||||
// Dur adds the fields key with d divided by unit and stored as a float.
|
||||
func (c Context) Dur(key string, d time.Duration) Context {
|
||||
c.l.context = json.AppendDuration(json.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
c.l.context = appendDuration(appendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return c
|
||||
}
|
||||
|
||||
// Durs adds the fields key with d divided by unit and stored as a float.
|
||||
func (c Context) Durs(key string, d []time.Duration) Context {
|
||||
c.l.context = json.AppendDurations(json.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
c.l.context = appendDurations(appendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return c
|
||||
}
|
||||
|
||||
// Interface adds the field key with obj marshaled using reflection.
|
||||
func (c Context) Interface(key string, i interface{}) Context {
|
||||
c.l.context = json.AppendInterface(json.AppendKey(c.l.context, key), i)
|
||||
c.l.context = appendInterface(appendKey(c.l.context, key), i)
|
||||
return c
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// +build !binary_log
|
||||
|
||||
package diode_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
diodes "code.cloudfoundry.org/go-diodes"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/diode"
|
||||
)
|
||||
|
||||
func ExampleNewWriter() {
|
||||
d := diodes.NewManyToOne(1000, diodes.AlertFunc(func(missed int) {
|
||||
fmt.Printf("Dropped %d messages\n", missed)
|
||||
}))
|
||||
w := diode.NewWriter(os.Stdout, d, 10*time.Millisecond)
|
||||
log := zerolog.New(w)
|
||||
log.Print("test")
|
||||
|
||||
w.Close()
|
||||
|
||||
// Output: {"level":"debug","message":"test"}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package diode_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
@ -11,19 +12,24 @@ import (
|
|||
diodes "code.cloudfoundry.org/go-diodes"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/diode"
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
func ExampleNewWriter() {
|
||||
func TestNewWriter(t *testing.T) {
|
||||
d := diodes.NewManyToOne(1000, diodes.AlertFunc(func(missed int) {
|
||||
fmt.Printf("Dropped %d messages\n", missed)
|
||||
}))
|
||||
w := diode.NewWriter(os.Stdout, d, 10*time.Millisecond)
|
||||
buf := bytes.Buffer{}
|
||||
w := diode.NewWriter(&buf, d, 10*time.Millisecond)
|
||||
log := zerolog.New(w)
|
||||
log.Print("test")
|
||||
|
||||
w.Close()
|
||||
|
||||
// Output: {"level":"debug","message":"test"}
|
||||
want := "{\"level\":\"debug\",\"message\":\"test\"}\n"
|
||||
got := cbor.DecodeIfBinaryToString(buf.Bytes())
|
||||
if got != want {
|
||||
t.Errorf("Diode New Writer Test failed. got:%s, want:%s!", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark(b *testing.B) {
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
// +build binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
// This file contains bindings to do binary encoding.
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
func appendInterface(dst []byte, i interface{}) []byte {
|
||||
return cbor.AppendInterface(dst, i)
|
||||
}
|
||||
|
||||
func appendKey(dst []byte, s string) []byte {
|
||||
return cbor.AppendKey(dst, s)
|
||||
}
|
||||
|
||||
func appendFloats64(dst []byte, f []float64) []byte {
|
||||
return cbor.AppendFloats64(dst, f)
|
||||
}
|
||||
|
||||
func appendFloat64(dst []byte, f float64) []byte {
|
||||
return cbor.AppendFloat64(dst, f)
|
||||
}
|
||||
|
||||
func appendFloats32(dst []byte, f []float32) []byte {
|
||||
return cbor.AppendFloats32(dst, f)
|
||||
}
|
||||
|
||||
func appendFloat32(dst []byte, f float32) []byte {
|
||||
return cbor.AppendFloat32(dst, f)
|
||||
}
|
||||
|
||||
func appendUints64(dst []byte, i []uint64) []byte {
|
||||
return cbor.AppendUints64(dst, i)
|
||||
}
|
||||
|
||||
func appendUint64(dst []byte, i uint64) []byte {
|
||||
return cbor.AppendUint64(dst, i)
|
||||
}
|
||||
|
||||
func appendUints32(dst []byte, i []uint32) []byte {
|
||||
return cbor.AppendUints32(dst, i)
|
||||
}
|
||||
|
||||
func appendUint32(dst []byte, i uint32) []byte {
|
||||
return cbor.AppendUint32(dst, i)
|
||||
}
|
||||
|
||||
func appendUints16(dst []byte, i []uint16) []byte {
|
||||
return cbor.AppendUints16(dst, i)
|
||||
}
|
||||
|
||||
func appendUint16(dst []byte, i uint16) []byte {
|
||||
return cbor.AppendUint16(dst, i)
|
||||
}
|
||||
|
||||
func appendUints8(dst []byte, i []uint8) []byte {
|
||||
return cbor.AppendUints8(dst, i)
|
||||
}
|
||||
|
||||
func appendUint8(dst []byte, i uint8) []byte {
|
||||
return cbor.AppendUint8(dst, i)
|
||||
}
|
||||
|
||||
func appendUints(dst []byte, i []uint) []byte {
|
||||
return cbor.AppendUints(dst, i)
|
||||
}
|
||||
|
||||
func appendUint(dst []byte, i uint) []byte {
|
||||
return cbor.AppendUint(dst, i)
|
||||
}
|
||||
|
||||
func appendInts64(dst []byte, i []int64) []byte {
|
||||
return cbor.AppendInts64(dst, i)
|
||||
}
|
||||
|
||||
func appendInt64(dst []byte, i int64) []byte {
|
||||
return cbor.AppendInt64(dst, i)
|
||||
}
|
||||
|
||||
func appendInts32(dst []byte, i []int32) []byte {
|
||||
return cbor.AppendInts32(dst, i)
|
||||
}
|
||||
|
||||
func appendInt32(dst []byte, i int32) []byte {
|
||||
return cbor.AppendInt32(dst, i)
|
||||
}
|
||||
|
||||
func appendInts16(dst []byte, i []int16) []byte {
|
||||
return cbor.AppendInts16(dst, i)
|
||||
}
|
||||
|
||||
func appendInt16(dst []byte, i int16) []byte {
|
||||
return cbor.AppendInt16(dst, i)
|
||||
}
|
||||
|
||||
func appendInts8(dst []byte, i []int8) []byte {
|
||||
return cbor.AppendInts8(dst, i)
|
||||
}
|
||||
|
||||
func appendInt8(dst []byte, i int8) []byte {
|
||||
return cbor.AppendInt8(dst, i)
|
||||
}
|
||||
|
||||
func appendInts(dst []byte, i []int) []byte {
|
||||
return cbor.AppendInts(dst, i)
|
||||
}
|
||||
|
||||
func appendInt(dst []byte, i int) []byte {
|
||||
return cbor.AppendInt(dst, i)
|
||||
}
|
||||
|
||||
func appendBools(dst []byte, b []bool) []byte {
|
||||
return cbor.AppendBools(dst, b)
|
||||
}
|
||||
|
||||
func appendBool(dst []byte, b bool) []byte {
|
||||
return cbor.AppendBool(dst, b)
|
||||
}
|
||||
|
||||
func appendError(dst []byte, e error) []byte {
|
||||
return cbor.AppendError(dst, e)
|
||||
}
|
||||
|
||||
func appendErrors(dst []byte, e []error) []byte {
|
||||
return cbor.AppendErrors(dst, e)
|
||||
}
|
||||
|
||||
func appendString(dst []byte, s string) []byte {
|
||||
return cbor.AppendString(dst, s)
|
||||
}
|
||||
|
||||
func appendStrings(dst []byte, s []string) []byte {
|
||||
return cbor.AppendStrings(dst, s)
|
||||
}
|
||||
|
||||
func appendDuration(dst []byte, t time.Duration, d time.Duration, fmt bool) []byte {
|
||||
return cbor.AppendDuration(dst, t, d, fmt)
|
||||
}
|
||||
|
||||
func appendDurations(dst []byte, t []time.Duration, d time.Duration, fmt bool) []byte {
|
||||
return cbor.AppendDurations(dst, t, d, fmt)
|
||||
}
|
||||
|
||||
func appendTimes(dst []byte, t []time.Time, fmt string) []byte {
|
||||
return cbor.AppendTimes(dst, t, fmt)
|
||||
}
|
||||
|
||||
func appendTime(dst []byte, t time.Time, fmt string) []byte {
|
||||
return cbor.AppendTime(dst, t, fmt)
|
||||
}
|
||||
|
||||
func appendEndMarker(dst []byte) []byte {
|
||||
return cbor.AppendEndMarker(dst)
|
||||
}
|
||||
|
||||
func appendLineBreak(dst []byte) []byte {
|
||||
// No line breaks needed in binary format.
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendBeginMarker(dst []byte) []byte {
|
||||
return cbor.AppendBeginMarker(dst)
|
||||
}
|
||||
|
||||
func appendBytes(dst []byte, b []byte) []byte {
|
||||
return cbor.AppendBytes(dst, b)
|
||||
}
|
||||
|
||||
func appendArrayStart(dst []byte) []byte {
|
||||
return cbor.AppendArrayStart(dst)
|
||||
}
|
||||
|
||||
func appendArrayEnd(dst []byte) []byte {
|
||||
return cbor.AppendArrayEnd(dst)
|
||||
}
|
||||
|
||||
func appendArrayDelim(dst []byte) []byte {
|
||||
return cbor.AppendArrayDelim(dst)
|
||||
}
|
||||
|
||||
func appendObjectData(dst []byte, src []byte) []byte {
|
||||
// Map begin character is present in the src, which
|
||||
// should not be copied when appending to existing data.
|
||||
return cbor.AppendObjectData(dst, src[1:])
|
||||
}
|
||||
|
||||
func appendJSON(dst []byte, j []byte) []byte {
|
||||
return cbor.AppendEmbeddedJSON(dst, j)
|
||||
}
|
||||
|
||||
func appendNil(dst []byte) []byte {
|
||||
return cbor.AppendNull(dst)
|
||||
}
|
||||
|
||||
func appendHex(dst []byte, val []byte) []byte {
|
||||
return cbor.AppendHex(dst, val)
|
||||
}
|
||||
|
||||
// decodeIfBinaryToString - converts a binary formatted log msg to a
|
||||
// JSON formatted String Log message.
|
||||
func decodeIfBinaryToString(in []byte) string {
|
||||
return cbor.DecodeIfBinaryToString(in)
|
||||
}
|
||||
|
||||
func decodeObjectToStr(in []byte) string {
|
||||
return cbor.DecodeObjectToStr(in)
|
||||
}
|
||||
|
||||
// decodeIfBinaryToBytes - converts a binary formatted log msg to a
|
||||
// JSON formatted Bytes Log message.
|
||||
func decodeIfBinaryToBytes(in []byte) []byte {
|
||||
return cbor.DecodeIfBinaryToBytes(in)
|
||||
}
|
|
@ -0,0 +1,216 @@
|
|||
// +build !binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
// encoder_json.go file contains bindings to generate
|
||||
// JSON encoded byte stream.
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
func appendInterface(dst []byte, i interface{}) []byte {
|
||||
return json.AppendInterface(dst, i)
|
||||
}
|
||||
|
||||
func appendKey(dst []byte, s string) []byte {
|
||||
return json.AppendKey(dst, s)
|
||||
}
|
||||
|
||||
func appendFloats64(dst []byte, f []float64) []byte {
|
||||
return json.AppendFloats64(dst, f)
|
||||
}
|
||||
|
||||
func appendFloat64(dst []byte, f float64) []byte {
|
||||
return json.AppendFloat64(dst, f)
|
||||
}
|
||||
|
||||
func appendFloats32(dst []byte, f []float32) []byte {
|
||||
return json.AppendFloats32(dst, f)
|
||||
}
|
||||
|
||||
func appendFloat32(dst []byte, f float32) []byte {
|
||||
return json.AppendFloat32(dst, f)
|
||||
}
|
||||
|
||||
func appendUints64(dst []byte, i []uint64) []byte {
|
||||
return json.AppendUints64(dst, i)
|
||||
}
|
||||
|
||||
func appendUint64(dst []byte, i uint64) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendUints32(dst []byte, i []uint32) []byte {
|
||||
return json.AppendUints32(dst, i)
|
||||
}
|
||||
|
||||
func appendUint32(dst []byte, i uint32) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendUints16(dst []byte, i []uint16) []byte {
|
||||
return json.AppendUints16(dst, i)
|
||||
}
|
||||
|
||||
func appendUint16(dst []byte, i uint16) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendUints8(dst []byte, i []uint8) []byte {
|
||||
return json.AppendUints8(dst, i)
|
||||
}
|
||||
|
||||
func appendUint8(dst []byte, i uint8) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendUints(dst []byte, i []uint) []byte {
|
||||
return json.AppendUints(dst, i)
|
||||
}
|
||||
|
||||
func appendUint(dst []byte, i uint) []byte {
|
||||
return strconv.AppendUint(dst, uint64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts64(dst []byte, i []int64) []byte {
|
||||
return json.AppendInts64(dst, i)
|
||||
}
|
||||
|
||||
func appendInt64(dst []byte, i int64) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts32(dst []byte, i []int32) []byte {
|
||||
return json.AppendInts32(dst, i)
|
||||
}
|
||||
|
||||
func appendInt32(dst []byte, i int32) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts16(dst []byte, i []int16) []byte {
|
||||
return json.AppendInts16(dst, i)
|
||||
}
|
||||
|
||||
func appendInt16(dst []byte, i int16) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts8(dst []byte, i []int8) []byte {
|
||||
return json.AppendInts8(dst, i)
|
||||
}
|
||||
|
||||
func appendInt8(dst []byte, i int8) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendInts(dst []byte, i []int) []byte {
|
||||
return json.AppendInts(dst, i)
|
||||
}
|
||||
|
||||
func appendInt(dst []byte, i int) []byte {
|
||||
return strconv.AppendInt(dst, int64(i), 10)
|
||||
}
|
||||
|
||||
func appendBools(dst []byte, b []bool) []byte {
|
||||
return json.AppendBools(dst, b)
|
||||
}
|
||||
|
||||
func appendBool(dst []byte, b bool) []byte {
|
||||
return strconv.AppendBool(dst, b)
|
||||
}
|
||||
|
||||
func appendError(dst []byte, e error) []byte {
|
||||
return json.AppendError(dst, e)
|
||||
}
|
||||
|
||||
func appendErrors(dst []byte, e []error) []byte {
|
||||
return json.AppendErrors(dst, e)
|
||||
}
|
||||
|
||||
func appendString(dst []byte, s string) []byte {
|
||||
return json.AppendString(dst, s)
|
||||
}
|
||||
|
||||
func appendStrings(dst []byte, s []string) []byte {
|
||||
return json.AppendStrings(dst, s)
|
||||
}
|
||||
|
||||
func appendDuration(dst []byte, t time.Duration, d time.Duration, fmt bool) []byte {
|
||||
return json.AppendDuration(dst, t, d, fmt)
|
||||
}
|
||||
|
||||
func appendDurations(dst []byte, t []time.Duration, d time.Duration, fmt bool) []byte {
|
||||
return json.AppendDurations(dst, t, d, fmt)
|
||||
}
|
||||
|
||||
func appendTimes(dst []byte, t []time.Time, fmt string) []byte {
|
||||
return json.AppendTimes(dst, t, fmt)
|
||||
}
|
||||
|
||||
func appendTime(dst []byte, t time.Time, fmt string) []byte {
|
||||
return json.AppendTime(dst, t, fmt)
|
||||
}
|
||||
|
||||
func appendEndMarker(dst []byte) []byte {
|
||||
return append(dst, '}')
|
||||
}
|
||||
|
||||
func appendLineBreak(dst []byte) []byte {
|
||||
return append(dst, '\n')
|
||||
}
|
||||
|
||||
func appendBeginMarker(dst []byte) []byte {
|
||||
return append(dst, '{')
|
||||
}
|
||||
|
||||
func appendBytes(dst []byte, b []byte) []byte {
|
||||
return json.AppendBytes(dst, b)
|
||||
}
|
||||
|
||||
func appendArrayStart(dst []byte) []byte {
|
||||
return append(dst, '[')
|
||||
}
|
||||
|
||||
func appendArrayEnd(dst []byte) []byte {
|
||||
return append(dst, ']')
|
||||
}
|
||||
|
||||
func appendArrayDelim(dst []byte) []byte {
|
||||
if len(dst) > 0 {
|
||||
return append(dst, ',')
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendObjectData(dst []byte, src []byte) []byte {
|
||||
return json.AppendObjectData(dst, src)
|
||||
}
|
||||
|
||||
func appendJSON(dst []byte, j []byte) []byte {
|
||||
return append(dst, j...)
|
||||
}
|
||||
|
||||
func appendNil(dst []byte) []byte {
|
||||
return append(dst, "null"...)
|
||||
}
|
||||
|
||||
func decodeIfBinaryToString(in []byte) string {
|
||||
return string(in)
|
||||
}
|
||||
|
||||
func decodeObjectToStr(in []byte) string {
|
||||
return string(in)
|
||||
}
|
||||
|
||||
func decodeIfBinaryToBytes(in []byte) []byte {
|
||||
return in
|
||||
}
|
||||
|
||||
func appendHex(in []byte, val []byte) []byte {
|
||||
return json.AppendHex(in, val)
|
||||
}
|
114
event.go
114
event.go
|
@ -7,8 +7,6 @@ import (
|
|||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
var eventPool = &sync.Pool{
|
||||
|
@ -47,9 +45,9 @@ func newEvent(w LevelWriter, level Level, enabled bool) *Event {
|
|||
return &Event{}
|
||||
}
|
||||
e := eventPool.Get().(*Event)
|
||||
e.buf = e.buf[:1]
|
||||
e.buf = e.buf[:0]
|
||||
e.h = e.h[:0]
|
||||
e.buf[0] = '{'
|
||||
e.buf = appendBeginMarker(e.buf)
|
||||
e.w = w
|
||||
e.level = level
|
||||
return e
|
||||
|
@ -59,7 +57,8 @@ func (e *Event) write() (err error) {
|
|||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
e.buf = append(e.buf, '}', '\n')
|
||||
e.buf = appendEndMarker(e.buf)
|
||||
e.buf = appendLineBreak(e.buf)
|
||||
if e.w != nil {
|
||||
_, err = e.w.WriteLevel(e.level, e.buf)
|
||||
}
|
||||
|
@ -98,7 +97,7 @@ func (e *Event) Msg(msg string) {
|
|||
}
|
||||
}
|
||||
if msg != "" {
|
||||
e.buf = json.AppendString(json.AppendKey(e.buf, MessageFieldName), msg)
|
||||
e.buf = appendString(appendKey(e.buf, MessageFieldName), msg)
|
||||
}
|
||||
if e.done != nil {
|
||||
defer e.done(msg)
|
||||
|
@ -134,7 +133,8 @@ func (e *Event) Dict(key string, dict *Event) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = append(append(json.AppendKey(e.buf, key), dict.buf...), '}')
|
||||
dict.buf = appendEndMarker(dict.buf)
|
||||
e.buf = append(appendKey(e.buf, key), dict.buf...)
|
||||
eventPool.Put(dict)
|
||||
return e
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ func (e *Event) Array(key string, arr LogArrayMarshaler) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendKey(e.buf, key)
|
||||
e.buf = appendKey(e.buf, key)
|
||||
var a *Array
|
||||
if aa, ok := arr.(*Array); ok {
|
||||
a = aa
|
||||
|
@ -166,17 +166,9 @@ func (e *Event) Array(key string, arr LogArrayMarshaler) *Event {
|
|||
}
|
||||
|
||||
func (e *Event) appendObject(obj LogObjectMarshaler) {
|
||||
pos := len(e.buf)
|
||||
e.buf = appendBeginMarker(e.buf)
|
||||
obj.MarshalZerologObject(e)
|
||||
if pos < len(e.buf) {
|
||||
// As MarshalZerologObject will use event API, the first field will be
|
||||
// preceded by a comma. If at least one field has been added (buf grew),
|
||||
// we replace this coma by the opening bracket.
|
||||
e.buf[pos] = '{'
|
||||
} else {
|
||||
e.buf = append(e.buf, '{')
|
||||
}
|
||||
e.buf = append(e.buf, '}')
|
||||
e.buf = appendEndMarker(e.buf)
|
||||
}
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler interface.
|
||||
|
@ -184,7 +176,7 @@ func (e *Event) Object(key string, obj LogObjectMarshaler) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendKey(e.buf, key)
|
||||
e.buf = appendKey(e.buf, key)
|
||||
e.appendObject(obj)
|
||||
return e
|
||||
}
|
||||
|
@ -194,7 +186,7 @@ func (e *Event) Str(key, val string) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendString(json.AppendKey(e.buf, key), val)
|
||||
e.buf = appendString(appendKey(e.buf, key), val)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -203,7 +195,7 @@ func (e *Event) Strs(key string, vals []string) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendStrings(json.AppendKey(e.buf, key), vals)
|
||||
e.buf = appendStrings(appendKey(e.buf, key), vals)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -215,7 +207,7 @@ func (e *Event) Bytes(key string, val []byte) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendBytes(json.AppendKey(e.buf, key), val)
|
||||
e.buf = appendBytes(appendKey(e.buf, key), val)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -224,7 +216,7 @@ func (e *Event) Hex(key string, val []byte) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendHex(json.AppendKey(e.buf, key), val)
|
||||
e.buf = appendHex(appendKey(e.buf, key), val)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -236,7 +228,7 @@ func (e *Event) RawJSON(key string, b []byte) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = append(json.AppendKey(e.buf, key), b...)
|
||||
e.buf = appendJSON(appendKey(e.buf, key), b)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -247,7 +239,7 @@ func (e *Event) AnErr(key string, err error) *Event {
|
|||
return e
|
||||
}
|
||||
if err != nil {
|
||||
e.buf = json.AppendError(json.AppendKey(e.buf, key), err)
|
||||
e.buf = appendError(appendKey(e.buf, key), err)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
@ -258,7 +250,7 @@ func (e *Event) Errs(key string, errs []error) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendErrors(json.AppendKey(e.buf, key), errs)
|
||||
e.buf = appendErrors(appendKey(e.buf, key), errs)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -270,7 +262,7 @@ func (e *Event) Err(err error) *Event {
|
|||
return e
|
||||
}
|
||||
if err != nil {
|
||||
e.buf = json.AppendError(json.AppendKey(e.buf, ErrorFieldName), err)
|
||||
e.buf = appendError(appendKey(e.buf, ErrorFieldName), err)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
@ -280,7 +272,7 @@ func (e *Event) Bool(key string, b bool) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendBool(json.AppendKey(e.buf, key), b)
|
||||
e.buf = appendBool(appendKey(e.buf, key), b)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -289,7 +281,7 @@ func (e *Event) Bools(key string, b []bool) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendBools(json.AppendKey(e.buf, key), b)
|
||||
e.buf = appendBools(appendKey(e.buf, key), b)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -298,7 +290,7 @@ func (e *Event) Int(key string, i int) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInt(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -307,7 +299,7 @@ func (e *Event) Ints(key string, i []int) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInts(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -316,7 +308,7 @@ func (e *Event) Int8(key string, i int8) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt8(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInt8(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -325,7 +317,7 @@ func (e *Event) Ints8(key string, i []int8) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts8(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInts8(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -334,7 +326,7 @@ func (e *Event) Int16(key string, i int16) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt16(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInt16(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -343,7 +335,7 @@ func (e *Event) Ints16(key string, i []int16) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts16(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInts16(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -352,7 +344,7 @@ func (e *Event) Int32(key string, i int32) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt32(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInt32(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -361,7 +353,7 @@ func (e *Event) Ints32(key string, i []int32) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts32(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInts32(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -370,7 +362,7 @@ func (e *Event) Int64(key string, i int64) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInt64(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInt64(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -379,7 +371,7 @@ func (e *Event) Ints64(key string, i []int64) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendInts64(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInts64(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -388,7 +380,7 @@ func (e *Event) Uint(key string, i uint) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUint(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -397,7 +389,7 @@ func (e *Event) Uints(key string, i []uint) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUints(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -406,7 +398,7 @@ func (e *Event) Uint8(key string, i uint8) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint8(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUint8(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -415,7 +407,7 @@ func (e *Event) Uints8(key string, i []uint8) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints8(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUints8(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -424,7 +416,7 @@ func (e *Event) Uint16(key string, i uint16) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint16(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUint16(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -433,7 +425,7 @@ func (e *Event) Uints16(key string, i []uint16) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints16(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUints16(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -442,7 +434,7 @@ func (e *Event) Uint32(key string, i uint32) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint32(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUint32(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -451,7 +443,7 @@ func (e *Event) Uints32(key string, i []uint32) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints32(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUints32(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -460,7 +452,7 @@ func (e *Event) Uint64(key string, i uint64) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUint64(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUint64(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -469,7 +461,7 @@ func (e *Event) Uints64(key string, i []uint64) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendUints64(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendUints64(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -478,7 +470,7 @@ func (e *Event) Float32(key string, f float32) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendFloat32(json.AppendKey(e.buf, key), f)
|
||||
e.buf = appendFloat32(appendKey(e.buf, key), f)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -487,7 +479,7 @@ func (e *Event) Floats32(key string, f []float32) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendFloats32(json.AppendKey(e.buf, key), f)
|
||||
e.buf = appendFloats32(appendKey(e.buf, key), f)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -496,7 +488,7 @@ func (e *Event) Float64(key string, f float64) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendFloat64(json.AppendKey(e.buf, key), f)
|
||||
e.buf = appendFloat64(appendKey(e.buf, key), f)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -505,7 +497,7 @@ func (e *Event) Floats64(key string, f []float64) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendFloats64(json.AppendKey(e.buf, key), f)
|
||||
e.buf = appendFloats64(appendKey(e.buf, key), f)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -518,7 +510,7 @@ func (e *Event) Timestamp() *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendTime(json.AppendKey(e.buf, TimestampFieldName), TimestampFunc(), TimeFieldFormat)
|
||||
e.buf = appendTime(appendKey(e.buf, TimestampFieldName), TimestampFunc(), TimeFieldFormat)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -527,7 +519,7 @@ func (e *Event) Time(key string, t time.Time) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendTime(json.AppendKey(e.buf, key), t, TimeFieldFormat)
|
||||
e.buf = appendTime(appendKey(e.buf, key), t, TimeFieldFormat)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -536,7 +528,7 @@ func (e *Event) Times(key string, t []time.Time) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendTimes(json.AppendKey(e.buf, key), t, TimeFieldFormat)
|
||||
e.buf = appendTimes(appendKey(e.buf, key), t, TimeFieldFormat)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -547,7 +539,7 @@ func (e *Event) Dur(key string, d time.Duration) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendDuration(json.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
e.buf = appendDuration(appendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -558,7 +550,7 @@ func (e *Event) Durs(key string, d []time.Duration) *Event {
|
|||
if e == nil {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendDurations(json.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
e.buf = appendDurations(appendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -573,7 +565,7 @@ func (e *Event) TimeDiff(key string, t time.Time, start time.Time) *Event {
|
|||
if t.After(start) {
|
||||
d = t.Sub(start)
|
||||
}
|
||||
e.buf = json.AppendDuration(json.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
e.buf = appendDuration(appendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -585,7 +577,7 @@ func (e *Event) Interface(key string, i interface{}) *Event {
|
|||
if obj, ok := i.(LogObjectMarshaler); ok {
|
||||
return e.Object(key, obj)
|
||||
}
|
||||
e.buf = json.AppendInterface(json.AppendKey(e.buf, key), i)
|
||||
e.buf = appendInterface(appendKey(e.buf, key), i)
|
||||
return e
|
||||
}
|
||||
|
||||
|
@ -602,6 +594,6 @@ func (e *Event) caller(skip int) *Event {
|
|||
if !ok {
|
||||
return e
|
||||
}
|
||||
e.buf = json.AppendString(json.AppendKey(e.buf, CallerFieldName), file+":"+strconv.Itoa(line))
|
||||
e.buf = appendString(appendKey(e.buf, CallerFieldName), file+":"+strconv.Itoa(line))
|
||||
return e
|
||||
}
|
||||
|
|
108
fields.go
108
fields.go
|
@ -3,8 +3,6 @@ package zerolog
|
|||
import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/internal/json"
|
||||
)
|
||||
|
||||
func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||
|
@ -14,114 +12,114 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
|||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
dst = json.AppendKey(dst, key)
|
||||
dst = appendKey(dst, key)
|
||||
switch val := fields[key].(type) {
|
||||
case string:
|
||||
dst = json.AppendString(dst, val)
|
||||
dst = appendString(dst, val)
|
||||
case []byte:
|
||||
dst = json.AppendBytes(dst, val)
|
||||
dst = appendBytes(dst, val)
|
||||
case error:
|
||||
dst = json.AppendError(dst, val)
|
||||
dst = appendError(dst, val)
|
||||
case []error:
|
||||
dst = json.AppendErrors(dst, val)
|
||||
dst = appendErrors(dst, val)
|
||||
case bool:
|
||||
dst = json.AppendBool(dst, val)
|
||||
dst = appendBool(dst, val)
|
||||
case int:
|
||||
dst = json.AppendInt(dst, val)
|
||||
dst = appendInt(dst, val)
|
||||
case int8:
|
||||
dst = json.AppendInt8(dst, val)
|
||||
dst = appendInt8(dst, val)
|
||||
case int16:
|
||||
dst = json.AppendInt16(dst, val)
|
||||
dst = appendInt16(dst, val)
|
||||
case int32:
|
||||
dst = json.AppendInt32(dst, val)
|
||||
dst = appendInt32(dst, val)
|
||||
case int64:
|
||||
dst = json.AppendInt64(dst, val)
|
||||
dst = appendInt64(dst, val)
|
||||
case uint:
|
||||
dst = json.AppendUint(dst, val)
|
||||
dst = appendUint(dst, val)
|
||||
case uint8:
|
||||
dst = json.AppendUint8(dst, val)
|
||||
dst = appendUint8(dst, val)
|
||||
case uint16:
|
||||
dst = json.AppendUint16(dst, val)
|
||||
dst = appendUint16(dst, val)
|
||||
case uint32:
|
||||
dst = json.AppendUint32(dst, val)
|
||||
dst = appendUint32(dst, val)
|
||||
case uint64:
|
||||
dst = json.AppendUint64(dst, val)
|
||||
dst = appendUint64(dst, val)
|
||||
case float32:
|
||||
dst = json.AppendFloat32(dst, val)
|
||||
dst = appendFloat32(dst, val)
|
||||
case float64:
|
||||
dst = json.AppendFloat64(dst, val)
|
||||
dst = appendFloat64(dst, val)
|
||||
case time.Time:
|
||||
dst = json.AppendTime(dst, val, TimeFieldFormat)
|
||||
dst = appendTime(dst, val, TimeFieldFormat)
|
||||
case time.Duration:
|
||||
dst = json.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
dst = appendDuration(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
case *string:
|
||||
dst = json.AppendString(dst, *val)
|
||||
dst = appendString(dst, *val)
|
||||
case *bool:
|
||||
dst = json.AppendBool(dst, *val)
|
||||
dst = appendBool(dst, *val)
|
||||
case *int:
|
||||
dst = json.AppendInt(dst, *val)
|
||||
dst = appendInt(dst, *val)
|
||||
case *int8:
|
||||
dst = json.AppendInt8(dst, *val)
|
||||
dst = appendInt8(dst, *val)
|
||||
case *int16:
|
||||
dst = json.AppendInt16(dst, *val)
|
||||
dst = appendInt16(dst, *val)
|
||||
case *int32:
|
||||
dst = json.AppendInt32(dst, *val)
|
||||
dst = appendInt32(dst, *val)
|
||||
case *int64:
|
||||
dst = json.AppendInt64(dst, *val)
|
||||
dst = appendInt64(dst, *val)
|
||||
case *uint:
|
||||
dst = json.AppendUint(dst, *val)
|
||||
dst = appendUint(dst, *val)
|
||||
case *uint8:
|
||||
dst = json.AppendUint8(dst, *val)
|
||||
dst = appendUint8(dst, *val)
|
||||
case *uint16:
|
||||
dst = json.AppendUint16(dst, *val)
|
||||
dst = appendUint16(dst, *val)
|
||||
case *uint32:
|
||||
dst = json.AppendUint32(dst, *val)
|
||||
dst = appendUint32(dst, *val)
|
||||
case *uint64:
|
||||
dst = json.AppendUint64(dst, *val)
|
||||
dst = appendUint64(dst, *val)
|
||||
case *float32:
|
||||
dst = json.AppendFloat32(dst, *val)
|
||||
dst = appendFloat32(dst, *val)
|
||||
case *float64:
|
||||
dst = json.AppendFloat64(dst, *val)
|
||||
dst = appendFloat64(dst, *val)
|
||||
case *time.Time:
|
||||
dst = json.AppendTime(dst, *val, TimeFieldFormat)
|
||||
dst = appendTime(dst, *val, TimeFieldFormat)
|
||||
case *time.Duration:
|
||||
dst = json.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger)
|
||||
dst = appendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger)
|
||||
case []string:
|
||||
dst = json.AppendStrings(dst, val)
|
||||
dst = appendStrings(dst, val)
|
||||
case []bool:
|
||||
dst = json.AppendBools(dst, val)
|
||||
dst = appendBools(dst, val)
|
||||
case []int:
|
||||
dst = json.AppendInts(dst, val)
|
||||
dst = appendInts(dst, val)
|
||||
case []int8:
|
||||
dst = json.AppendInts8(dst, val)
|
||||
dst = appendInts8(dst, val)
|
||||
case []int16:
|
||||
dst = json.AppendInts16(dst, val)
|
||||
dst = appendInts16(dst, val)
|
||||
case []int32:
|
||||
dst = json.AppendInts32(dst, val)
|
||||
dst = appendInts32(dst, val)
|
||||
case []int64:
|
||||
dst = json.AppendInts64(dst, val)
|
||||
dst = appendInts64(dst, val)
|
||||
case []uint:
|
||||
dst = json.AppendUints(dst, val)
|
||||
dst = appendUints(dst, val)
|
||||
// case []uint8:
|
||||
// dst = appendUints8(dst, val)
|
||||
case []uint16:
|
||||
dst = json.AppendUints16(dst, val)
|
||||
dst = appendUints16(dst, val)
|
||||
case []uint32:
|
||||
dst = json.AppendUints32(dst, val)
|
||||
dst = appendUints32(dst, val)
|
||||
case []uint64:
|
||||
dst = json.AppendUints64(dst, val)
|
||||
dst = appendUints64(dst, val)
|
||||
case []float32:
|
||||
dst = json.AppendFloats32(dst, val)
|
||||
dst = appendFloats32(dst, val)
|
||||
case []float64:
|
||||
dst = json.AppendFloats64(dst, val)
|
||||
dst = appendFloats64(dst, val)
|
||||
case []time.Time:
|
||||
dst = json.AppendTimes(dst, val, TimeFieldFormat)
|
||||
dst = appendTimes(dst, val, TimeFieldFormat)
|
||||
case []time.Duration:
|
||||
dst = json.AppendDurations(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
dst = appendDurations(dst, val, DurationFieldUnit, DurationFieldInteger)
|
||||
case nil:
|
||||
dst = append(dst, "null"...)
|
||||
dst = appendNil(dst)
|
||||
default:
|
||||
dst = json.AppendInterface(dst, val)
|
||||
dst = appendInterface(dst, val)
|
||||
}
|
||||
}
|
||||
return dst
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build !binary_log
|
||||
|
||||
package hlog_test
|
||||
|
||||
import (
|
||||
|
|
|
@ -15,8 +15,17 @@ import (
|
|||
"net/http/httptest"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/internal/cbor"
|
||||
)
|
||||
|
||||
func decodeIfBinary(out *bytes.Buffer) string {
|
||||
p := out.Bytes()
|
||||
if len(p) == 0 || p[0] < 0x7F {
|
||||
return out.String()
|
||||
}
|
||||
return cbor.DecodeObjectToStr(p) + "\n"
|
||||
}
|
||||
|
||||
func TestNewHandler(t *testing.T) {
|
||||
log := zerolog.New(nil).With().
|
||||
Str("foo", "bar").
|
||||
|
@ -42,7 +51,7 @@ func TestURLHandler(t *testing.T) {
|
|||
}))
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"url":"/path?foo=bar"}`+"\n", out.String(); want != got {
|
||||
if want, got := `{"url":"/path?foo=bar"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +67,7 @@ func TestMethodHandler(t *testing.T) {
|
|||
}))
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"method":"POST"}`+"\n", out.String(); want != got {
|
||||
if want, got := `{"method":"POST"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +84,7 @@ func TestRequestHandler(t *testing.T) {
|
|||
}))
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"request":"POST /path?foo=bar"}`+"\n", out.String(); want != got {
|
||||
if want, got := `{"request":"POST /path?foo=bar"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +100,7 @@ func TestRemoteAddrHandler(t *testing.T) {
|
|||
}))
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"ip":"1.2.3.4"}`+"\n", out.String(); want != got {
|
||||
if want, got := `{"ip":"1.2.3.4"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +116,7 @@ func TestRemoteAddrHandlerIPv6(t *testing.T) {
|
|||
}))
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"ip":"2001:db8:a0b:12f0::1"}`+"\n", out.String(); want != got {
|
||||
if want, got := `{"ip":"2001:db8:a0b:12f0::1"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +134,7 @@ func TestUserAgentHandler(t *testing.T) {
|
|||
}))
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"ua":"some user agent string"}`+"\n", out.String(); want != got {
|
||||
if want, got := `{"ua":"some user agent string"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +152,7 @@ func TestRefererHandler(t *testing.T) {
|
|||
}))
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"referer":"http://foo.com/bar"}`+"\n", out.String(); want != got {
|
||||
if want, got := `{"referer":"http://foo.com/bar"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +174,7 @@ func TestRequestIDHandler(t *testing.T) {
|
|||
}
|
||||
l := FromRequest(r)
|
||||
l.Log().Msg("")
|
||||
if want, got := fmt.Sprintf(`{"id":"%s"}`+"\n", id), out.String(); want != got {
|
||||
if want, got := fmt.Sprintf(`{"id":"%s"}`+"\n", id), decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}))
|
||||
|
@ -185,7 +194,7 @@ func TestCombinedHandlers(t *testing.T) {
|
|||
}))))
|
||||
h = NewHandler(zerolog.New(out))(h)
|
||||
h.ServeHTTP(nil, r)
|
||||
if want, got := `{"method":"POST","request":"POST /path?foo=bar","url":"/path?foo=bar"}`+"\n", out.String(); want != got {
|
||||
if want, got := `{"method":"POST","request":"POST /path?foo=bar","url":"/path?foo=bar"}`+"\n", decodeIfBinary(out); want != got {
|
||||
t.Errorf("Invalid log output, got: %s, want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
|
40
hook_test.go
40
hook_test.go
|
@ -1,9 +1,9 @@
|
|||
package zerolog
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type LevelNameHook struct{}
|
||||
|
@ -51,7 +51,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook)
|
||||
log.Log().Msg("test message")
|
||||
if got, want := out.String(), `{"level_name":"nolevel","message":"test message"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level_name":"nolevel","message":"test message"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -59,7 +59,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook)
|
||||
log.Log().Msg("")
|
||||
if got, want := out.String(), `{"level_name":"nolevel"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level_name":"nolevel"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -67,7 +67,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook)
|
||||
log.Print("")
|
||||
if got, want := out.String(), `{"level":"debug","level_name":"debug"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"debug","level_name":"debug"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -75,7 +75,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -83,7 +83,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(copyHook)
|
||||
log.Log().Msg("")
|
||||
if got, want := out.String(), `{"copy_has_level":false,"copy_msg":""}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"copy_has_level":false,"copy_msg":""}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -91,7 +91,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(copyHook)
|
||||
log.Info().Msg("a message")
|
||||
if got, want := out.String(), `{"level":"info","copy_has_level":true,"copy_level":"info","copy_msg":"a message","message":"a message"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"info","copy_has_level":true,"copy_level":"info","copy_msg":"a message","message":"a message"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -99,7 +99,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -107,7 +107,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).Hook(simpleHook)
|
||||
log.Error().Msg("a message")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged","message":"a message"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged","message":"a message"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -116,7 +116,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Hook(levelNameHook).Output(out)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -125,7 +125,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Output(out).Hook(levelNameHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -134,7 +134,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Hook(levelNameHook).Hook(simpleHook).Output(out)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -143,7 +143,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Output(out).Hook(levelNameHook).Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -152,7 +152,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(ignored).Hook(levelNameHook).Output(out).Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -160,7 +160,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).With().Str("with", "pre").Logger()
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"pre","level_name":"error"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"pre","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -168,7 +168,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).With().Str("with", "post").Logger().Hook(levelNameHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"post","level_name":"error"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"post","level_name":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -176,7 +176,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).Hook(simpleHook).With().Str("with", "pre").Logger()
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"pre","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"pre","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -184,7 +184,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).With().Str("with", "post").Logger().Hook(levelNameHook).Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"post","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"post","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -192,7 +192,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Hook(levelNameHook).With().Str("with", "mixed").Logger().Hook(simpleHook)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error","with":"mixed","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"mixed","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -200,7 +200,7 @@ func TestHook(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Error().Msg("")
|
||||
if got, want := out.String(), `{"level":"error"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
Reference:
|
||||
CBOR Encoding is described in RFC7049 https://tools.ietf.org/html/rfc7049
|
||||
|
||||
|
||||
Tests and benchmark:
|
||||
|
||||
```
|
||||
sprint @ cbor>go test -v -benchmem -bench=.
|
||||
=== RUN TestDecodeInteger
|
||||
--- PASS: TestDecodeInteger (0.00s)
|
||||
=== RUN TestDecodeString
|
||||
--- PASS: TestDecodeString (0.00s)
|
||||
=== RUN TestDecodeArray
|
||||
--- PASS: TestDecodeArray (0.00s)
|
||||
=== RUN TestDecodeMap
|
||||
--- PASS: TestDecodeMap (0.00s)
|
||||
=== RUN TestDecodeBool
|
||||
--- PASS: TestDecodeBool (0.00s)
|
||||
=== RUN TestDecodeFloat
|
||||
--- PASS: TestDecodeFloat (0.00s)
|
||||
=== RUN TestDecodeTimestamp
|
||||
--- PASS: TestDecodeTimestamp (0.00s)
|
||||
=== RUN TestDecodeCbor2Json
|
||||
--- PASS: TestDecodeCbor2Json (0.00s)
|
||||
=== RUN TestAppendString
|
||||
--- PASS: TestAppendString (0.00s)
|
||||
=== RUN TestAppendBytes
|
||||
--- PASS: TestAppendBytes (0.00s)
|
||||
=== RUN TestAppendTimeNow
|
||||
--- PASS: TestAppendTimeNow (0.00s)
|
||||
=== RUN TestAppendTimePastPresentInteger
|
||||
--- PASS: TestAppendTimePastPresentInteger (0.00s)
|
||||
=== RUN TestAppendTimePastPresentFloat
|
||||
--- PASS: TestAppendTimePastPresentFloat (0.00s)
|
||||
=== RUN TestAppendNull
|
||||
--- PASS: TestAppendNull (0.00s)
|
||||
=== RUN TestAppendBool
|
||||
--- PASS: TestAppendBool (0.00s)
|
||||
=== RUN TestAppendBoolArray
|
||||
--- PASS: TestAppendBoolArray (0.00s)
|
||||
=== RUN TestAppendInt
|
||||
--- PASS: TestAppendInt (0.00s)
|
||||
=== RUN TestAppendIntArray
|
||||
--- PASS: TestAppendIntArray (0.00s)
|
||||
=== RUN TestAppendFloat32
|
||||
--- PASS: TestAppendFloat32 (0.00s)
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
pkg: github.com/toravir/zerolog/internal/cbor
|
||||
BenchmarkAppendString/MultiBytesLast-4 30000000 43.3 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/NoEncoding-4 30000000 48.2 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/EncodingFirst-4 30000000 48.2 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/EncodingMiddle-4 30000000 41.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/EncodingLast-4 30000000 51.8 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/MultiBytesFirst-4 50000000 38.0 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendString/MultiBytesMiddle-4 50000000 38.0 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendTime/Integer-4 50000000 39.6 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendTime/Float-4 30000000 56.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/uint8-4 50000000 29.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/uint16-4 50000000 30.3 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/uint32-4 50000000 37.1 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int8-4 100000000 21.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int16-4 50000000 25.8 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int32-4 50000000 26.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int-Positive-4 100000000 21.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int-Negative-4 100000000 20.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/uint64-4 50000000 36.7 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendInt/int64-4 30000000 39.6 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendFloat/Float32-4 50000000 23.9 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkAppendFloat/Float64-4 50000000 32.8 ns/op 0 B/op 0 allocs/op
|
||||
PASS
|
||||
ok github.com/toravir/zerolog/internal/cbor 34.969s
|
||||
sprint @ cbor>
|
||||
```
|
|
@ -0,0 +1,43 @@
|
|||
package cbor
|
||||
|
||||
// AppendKey adds a key (string) to the binary encoded log message
|
||||
func AppendKey(dst []byte, key string) []byte {
|
||||
if len(dst) < 1 {
|
||||
dst = AppendBeginMarker(dst)
|
||||
}
|
||||
return AppendString(dst, key)
|
||||
}
|
||||
|
||||
// AppendError adds the Error to the log message if error is NOT nil
|
||||
func AppendError(dst []byte, err error) []byte {
|
||||
if err == nil {
|
||||
return append(dst, `null`...)
|
||||
}
|
||||
return AppendString(dst, err.Error())
|
||||
}
|
||||
|
||||
// AppendErrors when given an array of errors,
|
||||
// adds them to the log message if a specific error is nil, then
|
||||
// Nil is added, or else the error string is added.
|
||||
func AppendErrors(dst []byte, errs []error) []byte {
|
||||
if len(errs) == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
dst = AppendArrayStart(dst)
|
||||
if errs[0] != nil {
|
||||
dst = AppendString(dst, errs[0].Error())
|
||||
} else {
|
||||
dst = AppendNull(dst)
|
||||
}
|
||||
if len(errs) > 1 {
|
||||
for _, err := range errs[1:] {
|
||||
if err == nil {
|
||||
dst = AppendNull(dst)
|
||||
continue
|
||||
}
|
||||
dst = AppendString(dst, err.Error())
|
||||
}
|
||||
}
|
||||
dst = AppendArrayEnd(dst)
|
||||
return dst
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
// Package cbor provides primitives for storing different data
|
||||
// in the CBOR (binary) format. CBOR is defined in RFC7049.
|
||||
package cbor
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
majorOffset = 5
|
||||
additionalMax = 23
|
||||
//Non Values
|
||||
additionalTypeBoolFalse byte = 20
|
||||
additionalTypeBoolTrue byte = 21
|
||||
additionalTypeNull byte = 22
|
||||
//Integer (+ve and -ve) Sub-types
|
||||
additionalTypeIntUint8 byte = 24
|
||||
additionalTypeIntUint16 byte = 25
|
||||
additionalTypeIntUint32 byte = 26
|
||||
additionalTypeIntUint64 byte = 27
|
||||
//Float Sub-types
|
||||
additionalTypeFloat16 byte = 25
|
||||
additionalTypeFloat32 byte = 26
|
||||
additionalTypeFloat64 byte = 27
|
||||
additionalTypeBreak byte = 31
|
||||
//Tag Sub-types
|
||||
additionalTypeTimestamp byte = 01
|
||||
additionalTypeEmbeddedJSON byte = 31
|
||||
additionalTypeTagHexString uint16 = 262
|
||||
//Unspecified number of elements
|
||||
additionalTypeInfiniteCount byte = 31
|
||||
)
|
||||
const (
|
||||
majorTypeUnsignedInt byte = iota << majorOffset // Major type 0
|
||||
majorTypeNegativeInt // Major type 1
|
||||
majorTypeByteString // Major type 2
|
||||
majorTypeUtf8String // Major type 3
|
||||
majorTypeArray // Major type 4
|
||||
majorTypeMap // Major type 5
|
||||
majorTypeTags // Major type 6
|
||||
majorTypeSimpleAndFloat // Major type 7
|
||||
)
|
||||
|
||||
const (
|
||||
maskOutAdditionalType byte = (7 << majorOffset)
|
||||
maskOutMajorType byte = 31
|
||||
)
|
||||
|
||||
const (
|
||||
float32Nan = "\xfa\x7f\xc0\x00\x00"
|
||||
float32PosInfinity = "\xfa\x7f\x80\x00\x00"
|
||||
float32NegInfinity = "\xfa\xff\x80\x00\x00"
|
||||
float64Nan = "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"
|
||||
float64PosInfinity = "\xfb\x7f\xf0\x00\x00\x00\x00\x00\x00"
|
||||
float64NegInfinity = "\xfb\xff\xf0\x00\x00\x00\x00\x00\x00"
|
||||
)
|
||||
|
||||
// IntegerTimeFieldFormat indicates the format of timestamp decoded
|
||||
// from an integer (time in seconds).
|
||||
var IntegerTimeFieldFormat = time.RFC3339
|
||||
|
||||
// NanoTimeFieldFormat indicates the format of timestamp decoded
|
||||
// from a float value (time in seconds and nano seconds).
|
||||
var NanoTimeFieldFormat = time.RFC3339Nano
|
||||
|
||||
func appendCborTypePrefix(dst []byte, major byte, number uint64) []byte {
|
||||
byteCount := 8
|
||||
var minor byte
|
||||
switch {
|
||||
case number < 256:
|
||||
byteCount = 1
|
||||
minor = additionalTypeIntUint8
|
||||
|
||||
case number < 65536:
|
||||
byteCount = 2
|
||||
minor = additionalTypeIntUint16
|
||||
|
||||
case number < 4294967296:
|
||||
byteCount = 4
|
||||
minor = additionalTypeIntUint32
|
||||
|
||||
default:
|
||||
byteCount = 8
|
||||
minor = additionalTypeIntUint64
|
||||
|
||||
}
|
||||
dst = append(dst, byte(major|minor))
|
||||
byteCount--
|
||||
for ; byteCount >= 0; byteCount-- {
|
||||
dst = append(dst, byte(number>>(uint(byteCount)*8)))
|
||||
}
|
||||
return dst
|
||||
}
|
|
@ -0,0 +1,548 @@
|
|||
package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var decodeTimeZone *time.Location
|
||||
|
||||
const hexTable = "0123456789abcdef"
|
||||
|
||||
func decodeIntAdditonalType(src []byte, minor byte) (int64, uint, error) {
|
||||
val := int64(0)
|
||||
bytesRead := 0
|
||||
if minor <= 23 {
|
||||
val = int64(minor)
|
||||
bytesRead = 0
|
||||
} else {
|
||||
switch minor {
|
||||
case additionalTypeIntUint8:
|
||||
bytesRead = 1
|
||||
case additionalTypeIntUint16:
|
||||
bytesRead = 2
|
||||
case additionalTypeIntUint32:
|
||||
bytesRead = 4
|
||||
case additionalTypeIntUint64:
|
||||
bytesRead = 8
|
||||
default:
|
||||
return 0, 0, fmt.Errorf("Invalid Additional Type: %d in decodeInteger (expected <28)", minor)
|
||||
}
|
||||
for i := 0; i < bytesRead; i++ {
|
||||
val = val * 256
|
||||
val += int64(src[i])
|
||||
}
|
||||
}
|
||||
return val, uint(bytesRead), nil
|
||||
}
|
||||
|
||||
func decodeInteger(src []byte) (int64, uint, error) {
|
||||
major := src[0] & maskOutAdditionalType
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeUnsignedInt && major != majorTypeNegativeInt {
|
||||
return 0, 0, fmt.Errorf("Major type is: %d in decodeInteger!! (expected 0 or 1)", major)
|
||||
}
|
||||
val, bytesRead, err := decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if major == 0 {
|
||||
return val, 1 + bytesRead, nil
|
||||
}
|
||||
return (-1 - val), 1 + bytesRead, nil
|
||||
}
|
||||
|
||||
func decodeFloat(src []byte) (float64, uint, error) {
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeSimpleAndFloat {
|
||||
return 0, 0, fmt.Errorf("Incorrect Major type is: %d in decodeFloat", major)
|
||||
}
|
||||
|
||||
switch minor {
|
||||
case additionalTypeFloat16:
|
||||
return 0, 0, fmt.Errorf("float16 is not suppported in decodeFloat")
|
||||
case additionalTypeFloat32:
|
||||
switch string(src[1:5]) {
|
||||
case float32Nan:
|
||||
return math.NaN(), 5, nil
|
||||
case float32PosInfinity:
|
||||
return math.Inf(0), 5, nil
|
||||
case float32NegInfinity:
|
||||
return math.Inf(-1), 5, nil
|
||||
}
|
||||
n := uint32(0)
|
||||
for i := 0; i < 4; i++ {
|
||||
n = n * 256
|
||||
n += uint32(src[i+1])
|
||||
}
|
||||
val := math.Float32frombits(n)
|
||||
return float64(val), 5, nil
|
||||
case additionalTypeFloat64:
|
||||
switch string(src[1:9]) {
|
||||
case float64Nan:
|
||||
return math.NaN(), 9, nil
|
||||
case float64PosInfinity:
|
||||
return math.Inf(0), 9, nil
|
||||
case float64NegInfinity:
|
||||
return math.Inf(-1), 9, nil
|
||||
}
|
||||
n := uint64(0)
|
||||
for i := 0; i < 8; i++ {
|
||||
n = n * 256
|
||||
n += uint64(src[i+1])
|
||||
}
|
||||
val := math.Float64frombits(n)
|
||||
return val, 9, nil
|
||||
}
|
||||
return 0, 0, fmt.Errorf("Invalid Additional Type: %d in decodeFloat", minor)
|
||||
}
|
||||
|
||||
func decodeStringComplex(dst []byte, s string, pos uint) []byte {
|
||||
i := int(pos)
|
||||
const hex = "0123456789abcdef"
|
||||
start := 0
|
||||
|
||||
for i < len(s) {
|
||||
b := s[i]
|
||||
if b >= utf8.RuneSelf {
|
||||
r, size := utf8.DecodeRuneInString(s[i:])
|
||||
if r == utf8.RuneError && size == 1 {
|
||||
// In case of error, first append previous simple characters to
|
||||
// the byte slice if any and append a replacement character code
|
||||
// in place of the invalid sequence.
|
||||
if start < i {
|
||||
dst = append(dst, s[start:i]...)
|
||||
}
|
||||
dst = append(dst, `\ufffd`...)
|
||||
i += size
|
||||
start = i
|
||||
continue
|
||||
}
|
||||
i += size
|
||||
continue
|
||||
}
|
||||
if b >= 0x20 && b <= 0x7e && b != '\\' && b != '"' {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
// We encountered a character that needs to be encoded.
|
||||
// Let's append the previous simple characters to the byte slice
|
||||
// and switch our operation to read and encode the remainder
|
||||
// characters byte-by-byte.
|
||||
if start < i {
|
||||
dst = append(dst, s[start:i]...)
|
||||
}
|
||||
switch b {
|
||||
case '"', '\\':
|
||||
dst = append(dst, '\\', b)
|
||||
case '\b':
|
||||
dst = append(dst, '\\', 'b')
|
||||
case '\f':
|
||||
dst = append(dst, '\\', 'f')
|
||||
case '\n':
|
||||
dst = append(dst, '\\', 'n')
|
||||
case '\r':
|
||||
dst = append(dst, '\\', 'r')
|
||||
case '\t':
|
||||
dst = append(dst, '\\', 't')
|
||||
default:
|
||||
dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
|
||||
}
|
||||
i++
|
||||
start = i
|
||||
}
|
||||
if start < len(s) {
|
||||
dst = append(dst, s[start:]...)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func decodeString(src []byte, noQuotes bool) ([]byte, uint, error) {
|
||||
major := src[0] & maskOutAdditionalType
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeByteString {
|
||||
return []byte{}, 0, fmt.Errorf("Major type is: %d in decodeString", major)
|
||||
}
|
||||
result := []byte{'"'}
|
||||
if noQuotes {
|
||||
result = []byte{}
|
||||
}
|
||||
length, bytesRead, err := decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
return []byte{}, 0, err
|
||||
}
|
||||
bytesRead++
|
||||
st := bytesRead
|
||||
len := uint(length)
|
||||
bytesRead += len
|
||||
|
||||
result = append(result, src[st:st+len]...)
|
||||
if noQuotes {
|
||||
return result, bytesRead, nil
|
||||
}
|
||||
return append(result, '"'), bytesRead, nil
|
||||
}
|
||||
|
||||
func decodeUTF8String(src []byte) ([]byte, uint, error) {
|
||||
major := src[0] & maskOutAdditionalType
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeUtf8String {
|
||||
return []byte{}, 0, fmt.Errorf("Major type is: %d in decodeUTF8String", major)
|
||||
}
|
||||
result := []byte{'"'}
|
||||
length, bytesRead, err := decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
return []byte{}, 0, err
|
||||
}
|
||||
bytesRead++
|
||||
st := bytesRead
|
||||
len := uint(length)
|
||||
bytesRead += len
|
||||
|
||||
for i := st; i < bytesRead; i++ {
|
||||
// Check if the character needs encoding. Control characters, slashes,
|
||||
// and the double quote need json encoding. Bytes above the ascii
|
||||
// boundary needs utf8 encoding.
|
||||
if src[i] < 0x20 || src[i] > 0x7e || src[i] == '\\' || src[i] == '"' {
|
||||
// We encountered a character that needs to be encoded. Switch
|
||||
// to complex version of the algorithm.
|
||||
dst := []byte{'"'}
|
||||
dst = decodeStringComplex(dst, string(src[st:st+len]), i-st)
|
||||
return append(dst, '"'), bytesRead, nil
|
||||
}
|
||||
}
|
||||
// The string has no need for encoding an therefore is directly
|
||||
// appended to the byte slice.
|
||||
result = append(result, src[st:st+len]...)
|
||||
return append(result, '"'), bytesRead, nil
|
||||
}
|
||||
|
||||
func array2Json(src []byte, dst io.Writer) (uint, error) {
|
||||
dst.Write([]byte{'['})
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeArray {
|
||||
return 0, fmt.Errorf("Major type is: %d in array2Json", major)
|
||||
}
|
||||
len := 0
|
||||
bytesRead := uint(0)
|
||||
unSpecifiedCount := false
|
||||
if minor == additionalTypeInfiniteCount {
|
||||
unSpecifiedCount = true
|
||||
bytesRead = 1
|
||||
} else {
|
||||
var length int64
|
||||
var err error
|
||||
length, bytesRead, err = decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
fmt.Println("Error!!!")
|
||||
return 0, err
|
||||
}
|
||||
len = int(length)
|
||||
bytesRead++
|
||||
}
|
||||
curPos := bytesRead
|
||||
for i := 0; unSpecifiedCount || i < len; i++ {
|
||||
bc, err := Cbor2JsonOneObject(src[curPos:], dst)
|
||||
if err != nil {
|
||||
if src[curPos] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) {
|
||||
bytesRead++
|
||||
break
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
curPos += bc
|
||||
bytesRead += bc
|
||||
if unSpecifiedCount {
|
||||
if src[curPos] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) {
|
||||
bytesRead++
|
||||
break
|
||||
}
|
||||
dst.Write([]byte{','})
|
||||
} else if i+1 < len {
|
||||
dst.Write([]byte{','})
|
||||
}
|
||||
}
|
||||
dst.Write([]byte{']'})
|
||||
return bytesRead, nil
|
||||
}
|
||||
|
||||
func map2Json(src []byte, dst io.Writer) (uint, error) {
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeMap {
|
||||
return 0, fmt.Errorf("Major type is: %d in map2Json", major)
|
||||
}
|
||||
len := 0
|
||||
bytesRead := uint(0)
|
||||
unSpecifiedCount := false
|
||||
if minor == additionalTypeInfiniteCount {
|
||||
unSpecifiedCount = true
|
||||
bytesRead = 1
|
||||
} else {
|
||||
var length int64
|
||||
var err error
|
||||
length, bytesRead, err = decodeIntAdditonalType(src[1:], minor)
|
||||
if err != nil {
|
||||
fmt.Println("Error!!!")
|
||||
return 0, err
|
||||
}
|
||||
len = int(length)
|
||||
bytesRead++
|
||||
}
|
||||
if len%2 == 1 {
|
||||
return 0, fmt.Errorf("Invalid Length of map %d - has to be even", len)
|
||||
}
|
||||
dst.Write([]byte{'{'})
|
||||
curPos := bytesRead
|
||||
for i := 0; unSpecifiedCount || i < len; i++ {
|
||||
bc, err := Cbor2JsonOneObject(src[curPos:], dst)
|
||||
if err != nil {
|
||||
//We hit the BREAK
|
||||
if src[curPos] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) {
|
||||
bytesRead++
|
||||
break
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
curPos += bc
|
||||
bytesRead += bc
|
||||
if i%2 == 0 {
|
||||
//Even position values are keys
|
||||
dst.Write([]byte{':'})
|
||||
} else {
|
||||
if unSpecifiedCount {
|
||||
if src[curPos] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) {
|
||||
bytesRead++
|
||||
break
|
||||
}
|
||||
dst.Write([]byte{','})
|
||||
} else if i+1 < len {
|
||||
dst.Write([]byte{','})
|
||||
}
|
||||
}
|
||||
}
|
||||
dst.Write([]byte{'}'})
|
||||
return bytesRead, nil
|
||||
}
|
||||
|
||||
func decodeTagData(src []byte) ([]byte, uint, error) {
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeTags {
|
||||
return nil, 0, fmt.Errorf("Major type is: %d in decodeTagData", major)
|
||||
}
|
||||
if minor == additionalTypeTimestamp {
|
||||
tsMajor := src[1] & maskOutAdditionalType
|
||||
if tsMajor == majorTypeUnsignedInt || tsMajor == majorTypeNegativeInt {
|
||||
n, bc, err := decodeInteger(src[1:])
|
||||
if err != nil {
|
||||
return []byte{}, 0, err
|
||||
}
|
||||
t := time.Unix(n, 0)
|
||||
if decodeTimeZone != nil {
|
||||
t = t.In(decodeTimeZone)
|
||||
} else {
|
||||
t = t.In(time.UTC)
|
||||
}
|
||||
tsb := []byte{}
|
||||
tsb = append(tsb, '"')
|
||||
tsb = t.AppendFormat(tsb, IntegerTimeFieldFormat)
|
||||
tsb = append(tsb, '"')
|
||||
return tsb, 1 + bc, nil
|
||||
} else if tsMajor == majorTypeSimpleAndFloat {
|
||||
n, bc, err := decodeFloat(src[1:])
|
||||
if err != nil {
|
||||
return []byte{}, 0, err
|
||||
}
|
||||
secs := int64(n)
|
||||
n -= float64(secs)
|
||||
n *= float64(1e9)
|
||||
t := time.Unix(secs, int64(n))
|
||||
if decodeTimeZone != nil {
|
||||
t = t.In(decodeTimeZone)
|
||||
} else {
|
||||
t = t.In(time.UTC)
|
||||
}
|
||||
tsb := []byte{}
|
||||
tsb = append(tsb, '"')
|
||||
tsb = t.AppendFormat(tsb, NanoTimeFieldFormat)
|
||||
tsb = append(tsb, '"')
|
||||
return tsb, 1 + bc, nil
|
||||
} else {
|
||||
return nil, 0, fmt.Errorf("TS format is neigther int nor float: %d", tsMajor)
|
||||
}
|
||||
} else if minor == additionalTypeEmbeddedJSON {
|
||||
dataMajor := src[1] & maskOutAdditionalType
|
||||
if dataMajor == majorTypeByteString {
|
||||
emb, bc, err := decodeString(src[1:], true)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return emb, 1 + bc, nil
|
||||
}
|
||||
return nil, 0, fmt.Errorf("Unsupported embedded Type: %d in decodeEmbeddedJSON", dataMajor)
|
||||
} else if minor == additionalTypeIntUint16 {
|
||||
val,_,_ := decodeIntAdditonalType(src[1:], minor)
|
||||
if uint16(val) == additionalTypeTagHexString {
|
||||
emb, bc, _ := decodeString(src[3:], true)
|
||||
dst := []byte{'"'}
|
||||
for _, v := range emb {
|
||||
dst = append(dst, hexTable[v>>4], hexTable[v&0x0f])
|
||||
}
|
||||
return append(dst, '"'), 3+bc, nil
|
||||
}
|
||||
}
|
||||
return nil, 0, fmt.Errorf("Unsupported Additional Type: %d in decodeTagData", minor)
|
||||
}
|
||||
|
||||
func decodeSimpleFloat(src []byte) ([]byte, uint, error) {
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
minor := src[0] & maskOutMajorType
|
||||
if major != majorTypeSimpleAndFloat {
|
||||
return nil, 0, fmt.Errorf("Major type is: %d in decodeSimpleFloat", major)
|
||||
}
|
||||
switch minor {
|
||||
case additionalTypeBoolTrue:
|
||||
return []byte("true"), 1, nil
|
||||
case additionalTypeBoolFalse:
|
||||
return []byte("false"), 1, nil
|
||||
case additionalTypeNull:
|
||||
return []byte("null"), 1, nil
|
||||
|
||||
case additionalTypeFloat16:
|
||||
fallthrough
|
||||
case additionalTypeFloat32:
|
||||
fallthrough
|
||||
case additionalTypeFloat64:
|
||||
v, bc, err := decodeFloat(src)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
ba := []byte{}
|
||||
switch {
|
||||
case math.IsNaN(v):
|
||||
return []byte("\"NaN\""), bc, nil
|
||||
case math.IsInf(v, 1):
|
||||
return []byte("\"+Inf\""), bc, nil
|
||||
case math.IsInf(v, -1):
|
||||
return []byte("\"-Inf\""), bc, nil
|
||||
}
|
||||
if bc == 5 {
|
||||
ba = strconv.AppendFloat(ba, v, 'f', -1, 32)
|
||||
} else {
|
||||
ba = strconv.AppendFloat(ba, v, 'f', -1, 64)
|
||||
}
|
||||
return ba, bc, nil
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("Invalid Additional Type: %d in decodeSimpleFloat", minor)
|
||||
}
|
||||
}
|
||||
|
||||
// Cbor2JsonOneObject takes in byte array and decodes ONE CBOR Object
|
||||
// usually a MAP. Use this when only ONE CBOR object needs decoding.
|
||||
// Decoded string is written to the dst.
|
||||
// Returns the bytes decoded and if any error was encountered.
|
||||
func Cbor2JsonOneObject(src []byte, dst io.Writer) (uint, error) {
|
||||
var err error
|
||||
major := (src[0] & maskOutAdditionalType)
|
||||
bc := uint(0)
|
||||
var s []byte
|
||||
switch major {
|
||||
case majorTypeUnsignedInt:
|
||||
fallthrough
|
||||
case majorTypeNegativeInt:
|
||||
var n int64
|
||||
n, bc, err = decodeInteger(src)
|
||||
dst.Write([]byte(strconv.Itoa(int(n))))
|
||||
|
||||
case majorTypeByteString:
|
||||
s, bc, err = decodeString(src, false)
|
||||
dst.Write(s)
|
||||
|
||||
case majorTypeUtf8String:
|
||||
s, bc, err = decodeUTF8String(src)
|
||||
dst.Write(s)
|
||||
|
||||
case majorTypeArray:
|
||||
bc, err = array2Json(src, dst)
|
||||
|
||||
case majorTypeMap:
|
||||
bc, err = map2Json(src, dst)
|
||||
|
||||
case majorTypeTags:
|
||||
s, bc, err = decodeTagData(src)
|
||||
dst.Write(s)
|
||||
|
||||
case majorTypeSimpleAndFloat:
|
||||
s, bc, err = decodeSimpleFloat(src)
|
||||
dst.Write(s)
|
||||
}
|
||||
return bc, err
|
||||
}
|
||||
|
||||
// Cbor2JsonManyObjects decodes all the CBOR Objects present in the
|
||||
// source byte array. It keeps on decoding until it runs out of bytes.
|
||||
// Decoded string is written to the dst. At the end of every CBOR Object
|
||||
// newline is written to the output stream.
|
||||
// Returns the number of bytes decoded and if any error was encountered.
|
||||
func Cbor2JsonManyObjects(src []byte, dst io.Writer) (uint, error) {
|
||||
curPos := uint(0)
|
||||
totalBytes := uint(len(src))
|
||||
for curPos < totalBytes {
|
||||
bc, err := Cbor2JsonOneObject(src[curPos:], dst)
|
||||
if err != nil {
|
||||
return curPos, err
|
||||
}
|
||||
dst.Write([]byte("\n"))
|
||||
curPos += bc
|
||||
}
|
||||
return curPos, nil
|
||||
}
|
||||
|
||||
// Detect if the bytes to be printed is Binary or not.
|
||||
func binaryFmt(p []byte) bool {
|
||||
if len(p) > 0 && p[0] > 0x7F {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// DecodeIfBinaryToString converts a binary formatted log msg to a
|
||||
// JSON formatted String Log message - suitable for printing to Console/Syslog.
|
||||
func DecodeIfBinaryToString(in []byte) string {
|
||||
if binaryFmt(in) {
|
||||
var b bytes.Buffer
|
||||
Cbor2JsonManyObjects(in, &b)
|
||||
return b.String()
|
||||
}
|
||||
return string(in)
|
||||
}
|
||||
|
||||
// DecodeObjectToStr checks if the input is a binary format, if so,
|
||||
// it will decode a single Object and return the decoded string.
|
||||
func DecodeObjectToStr(in []byte) string {
|
||||
if binaryFmt(in) {
|
||||
var b bytes.Buffer
|
||||
Cbor2JsonOneObject(in, &b)
|
||||
return b.String()
|
||||
}
|
||||
return string(in)
|
||||
}
|
||||
|
||||
// DecodeIfBinaryToBytes checks if the input is a binary format, if so,
|
||||
// it will decode all Objects and return the decoded string as byte array.
|
||||
func DecodeIfBinaryToBytes(in []byte) []byte {
|
||||
if binaryFmt(in) {
|
||||
var b bytes.Buffer
|
||||
Cbor2JsonManyObjects(in, &b)
|
||||
return b.Bytes()
|
||||
}
|
||||
return in
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDecodeInteger(t *testing.T) {
|
||||
for _, tc := range integerTestCases {
|
||||
gotv, gotc, err := decodeInteger([]byte(tc.binary))
|
||||
if gotv != int64(tc.val) || int(gotc) != len(tc.binary) || err != nil {
|
||||
t.Errorf("decodeInteger(0x%s)=0x%d, want: 0x%d",
|
||||
hex.EncodeToString([]byte(tc.binary)), gotv, tc.val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeString(t *testing.T) {
|
||||
for _, tt := range encodeStringTests {
|
||||
got, _, err := decodeUTF8String([]byte(tt.binary))
|
||||
if err != nil {
|
||||
t.Errorf("Got Error for the case: %s", hex.EncodeToString([]byte(tt.binary)))
|
||||
}
|
||||
if string(got) != "\""+tt.json+"\"" {
|
||||
t.Errorf("DecodeString(0x%s)=%s, want:\"%s\"\n", hex.EncodeToString([]byte(tt.binary)), string(got),
|
||||
hex.EncodeToString([]byte(tt.json)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeArray(t *testing.T) {
|
||||
for _, tc := range integerArrayTestCases {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
_, err := array2Json([]byte(tc.binary), buf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if buf.String() != tc.json {
|
||||
t.Errorf("array2Json(0x%s)=%s, want: %s", hex.EncodeToString([]byte(tc.binary)), buf.String(), tc.json)
|
||||
}
|
||||
}
|
||||
//Unspecified Length Array
|
||||
var infiniteArrayTestCases = []struct {
|
||||
in string
|
||||
out string
|
||||
}{
|
||||
{"\x9f\x20\x00\x18\xc8\x14\xff", "[-1,0,200,20]"},
|
||||
{"\x9f\x38\xc7\x29\x18\xc8\x19\x01\x90\xff", "[-200,-10,200,400]"},
|
||||
{"\x9f\x01\x02\x03\xff", "[1,2,3]"},
|
||||
{"\x9f\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x18\x18\x19\xff",
|
||||
"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]"},
|
||||
}
|
||||
for _, tc := range infiniteArrayTestCases {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
_, err := array2Json([]byte(tc.in), buf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if buf.String() != tc.out {
|
||||
t.Errorf("array2Json(0x%s)=%s, want: %s", hex.EncodeToString([]byte(tc.out)), buf.String(), tc.out)
|
||||
}
|
||||
}
|
||||
for _, tc := range booleanArrayTestCases {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
_, err := array2Json([]byte(tc.binary), buf)
|
||||
if err != nil {
|
||||
t.Errorf("array2Json(0x%s) errored out: %s", hex.EncodeToString([]byte(tc.binary)), err.Error())
|
||||
}
|
||||
if buf.String() != tc.json {
|
||||
t.Errorf("array2Json(0x%s)=%s, want: %s", hex.EncodeToString([]byte(tc.binary)), buf.String(), tc.json)
|
||||
}
|
||||
}
|
||||
//TODO add cases for arrays of other types
|
||||
}
|
||||
|
||||
var infiniteMapDecodeTestCases = []struct {
|
||||
bin []byte
|
||||
json string
|
||||
}{
|
||||
{[]byte("\xbf\x64IETF\x20\xff"), "{\"IETF\":-1}"},
|
||||
{[]byte("\xbf\x65Array\x84\x20\x00\x18\xc8\x14\xff"), "{\"Array\":[-1,0,200,20]}"},
|
||||
}
|
||||
|
||||
var mapDecodeTestCases = []struct {
|
||||
bin []byte
|
||||
json string
|
||||
}{
|
||||
{[]byte("\xa2\x64IETF\x20"), "{\"IETF\":-1}"},
|
||||
{[]byte("\xa2\x65Array\x84\x20\x00\x18\xc8\x14"), "{\"Array\":[-1,0,200,20]}"},
|
||||
}
|
||||
|
||||
func TestDecodeMap(t *testing.T) {
|
||||
for _, tc := range mapDecodeTestCases {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
_, err := map2Json(tc.bin, buf)
|
||||
if err != nil {
|
||||
t.Errorf("map2Json(0x%s) returned error", err)
|
||||
}
|
||||
if buf.String() != tc.json {
|
||||
t.Errorf("map2Json(0x%s)=%s, want: %s", hex.EncodeToString(tc.bin), buf.String(), tc.json)
|
||||
}
|
||||
}
|
||||
for _, tc := range infiniteMapDecodeTestCases {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
_, err := map2Json(tc.bin, buf)
|
||||
if err != nil {
|
||||
t.Errorf("map2Json(0x%s) returned error", err)
|
||||
}
|
||||
if buf.String() != tc.json {
|
||||
t.Errorf("map2Json(0x%s)=%s, want: %s", hex.EncodeToString(tc.bin), buf.String(), tc.json)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeBool(t *testing.T) {
|
||||
for _, tc := range booleanTestCases {
|
||||
got, _, err := decodeSimpleFloat([]byte(tc.binary))
|
||||
if err != nil {
|
||||
t.Errorf("decodeSimpleFloat(0x%s) errored %s", hex.EncodeToString([]byte(tc.binary)), err.Error())
|
||||
}
|
||||
if string(got) != tc.json {
|
||||
t.Errorf("decodeSimpleFloat(0x%s)=%s, want:%s", hex.EncodeToString([]byte(tc.binary)), string(got), tc.json)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeFloat(t *testing.T) {
|
||||
for _, tc := range float32TestCases {
|
||||
got, _, err := decodeFloat([]byte(tc.binary))
|
||||
if err != nil {
|
||||
t.Errorf("decodeFloat(0x%s) returned error: %s", hex.EncodeToString([]byte(tc.binary)), err.Error())
|
||||
}
|
||||
if got != float64(tc.val) {
|
||||
t.Errorf("decodeFloat(0x%s)=%f, want:%f", hex.EncodeToString([]byte(tc.binary)), got, tc.val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeTimestamp(t *testing.T) {
|
||||
decodeTimeZone, _ = time.LoadLocation("UTC")
|
||||
for _, tc := range timeIntegerTestcases {
|
||||
tm, _, err := decodeTagData([]byte(tc.binary))
|
||||
if err != nil {
|
||||
t.Errorf("decodeTagData(0x%s) returned error: %s", hex.EncodeToString([]byte(tc.binary)), err.Error())
|
||||
}
|
||||
if string(tm) != "\""+tc.rfcStr+"\"" {
|
||||
t.Errorf("decodeFloat(0x%s)=%s, want:%s", hex.EncodeToString([]byte(tc.binary)), tm, tc.rfcStr)
|
||||
}
|
||||
}
|
||||
for _, tc := range timeFloatTestcases {
|
||||
tm, _, err := decodeTagData([]byte(tc.out))
|
||||
if err != nil {
|
||||
t.Errorf("decodeTagData(0x%s) returned error: %s", hex.EncodeToString([]byte(tc.out)), err.Error())
|
||||
}
|
||||
//Since we convert to float and back - it may be slightly off - so
|
||||
//we cannot check for exact equality instead, we'll check it is
|
||||
//very close to each other Less than a Microsecond (lets not yet do nanosec)
|
||||
|
||||
got, _ := time.Parse(string(tm), string(tm))
|
||||
want, _ := time.Parse(tc.rfcStr, tc.rfcStr)
|
||||
if got.Sub(want) > time.Microsecond {
|
||||
t.Errorf("decodeFloat(0x%s)=%s, want:%s", hex.EncodeToString([]byte(tc.out)), tm, tc.rfcStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var compositeCborTestCases = []struct {
|
||||
binary []byte
|
||||
json string
|
||||
}{
|
||||
{[]byte("\xbf\x64IETF\x20\x65Array\x9f\x20\x00\x18\xc8\x14\xff\xff"), "{\"IETF\":-1,\"Array\":[-1,0,200,20]}\n"},
|
||||
{[]byte("\xbf\x64IETF\x64YES!\x65Array\x9f\x20\x00\x18\xc8\x14\xff\xff"), "{\"IETF\":\"YES!\",\"Array\":[-1,0,200,20]}\n"},
|
||||
}
|
||||
|
||||
func TestDecodeCbor2Json(t *testing.T) {
|
||||
for _, tc := range compositeCborTestCases {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
_, err := Cbor2JsonManyObjects(tc.binary, buf)
|
||||
if err != nil {
|
||||
t.Errorf("cbor2JsonManyObjects(0x%s) returned error", err)
|
||||
}
|
||||
if buf.String() != tc.json {
|
||||
t.Errorf("cbor2JsonManyObjects(0x%s)=%s, want: %s", hex.EncodeToString(tc.binary), buf.String(), tc.json)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package cbor
|
||||
|
||||
// AppendStrings encodes and adds an array of strings to the dst byte array.
|
||||
func AppendStrings(dst []byte, vals []string) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendString(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendString encodes and adds a string to the dst byte array.
|
||||
func AppendString(dst []byte, s string) []byte {
|
||||
major := majorTypeUtf8String
|
||||
|
||||
l := len(s)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, majorTypeUtf8String, uint64(l))
|
||||
}
|
||||
return append(dst, s...)
|
||||
}
|
||||
|
||||
// AppendBytes encodes and adds an array of bytes to the dst byte array.
|
||||
func AppendBytes(dst, s []byte) []byte {
|
||||
major := majorTypeByteString
|
||||
|
||||
l := len(s)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
return append(dst, s...)
|
||||
}
|
||||
|
||||
// AppendEmbeddedJSON adds a tag and embeds input JSON as such.
|
||||
func AppendEmbeddedJSON(dst, s []byte) []byte {
|
||||
major := majorTypeTags
|
||||
minor := additionalTypeEmbeddedJSON
|
||||
dst = append(dst, byte(major|minor))
|
||||
|
||||
major = majorTypeByteString
|
||||
|
||||
l := len(s)
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
return append(dst, s...)
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package cbor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var encodeStringTests = []struct {
|
||||
plain string
|
||||
binary string
|
||||
json string //begin and end quotes are implied
|
||||
}{
|
||||
{"", "\x60", ""},
|
||||
{"\\", "\x61\x5c", "\\\\"},
|
||||
{"\x00", "\x61\x00", "\\u0000"},
|
||||
{"\x01", "\x61\x01", "\\u0001"},
|
||||
{"\x02", "\x61\x02", "\\u0002"},
|
||||
{"\x03", "\x61\x03", "\\u0003"},
|
||||
{"\x04", "\x61\x04", "\\u0004"},
|
||||
{"*", "\x61*", "*"},
|
||||
{"a", "\x61a", "a"},
|
||||
{"IETF", "\x64IETF", "IETF"},
|
||||
{"abcdefghijklmnopqrstuvwxyzABCD", "\x78\x1eabcdefghijklmnopqrstuvwxyzABCD", "abcdefghijklmnopqrstuvwxyzABCD"},
|
||||
{"<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->",
|
||||
"\x79\x01\x2c<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->",
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->"},
|
||||
{"emoji \u2764\ufe0f!", "\x6demoji ❤️!", "emoji \u2764\ufe0f!"},
|
||||
}
|
||||
|
||||
var encodeByteTests = []struct {
|
||||
plain []byte
|
||||
binary string
|
||||
}{
|
||||
{[]byte{}, "\x40"},
|
||||
{[]byte("\\"), "\x41\x5c"},
|
||||
{[]byte("\x00"), "\x41\x00"},
|
||||
{[]byte("\x01"), "\x41\x01"},
|
||||
{[]byte("\x02"), "\x41\x02"},
|
||||
{[]byte("\x03"), "\x41\x03"},
|
||||
{[]byte("\x04"), "\x41\x04"},
|
||||
{[]byte("*"), "\x41*"},
|
||||
{[]byte("a"), "\x41a"},
|
||||
{[]byte("IETF"), "\x44IETF"},
|
||||
{[]byte("abcdefghijklmnopqrstuvwxyzABCD"), "\x58\x1eabcdefghijklmnopqrstuvwxyzABCD"},
|
||||
{[]byte("<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->"),
|
||||
"\x59\x01\x2c<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->" +
|
||||
"<------------------------------------ This is a 100 character string ----------------------------->"},
|
||||
{[]byte("emoji \u2764\ufe0f!"), "\x4demoji ❤️!"},
|
||||
}
|
||||
|
||||
func TestAppendString(t *testing.T) {
|
||||
for _, tt := range encodeStringTests {
|
||||
b := AppendString([]byte{}, tt.plain)
|
||||
if got, want := string(b), tt.binary; got != want {
|
||||
t.Errorf("appendString(%q) = %#q, want %#q", tt.plain, got, want)
|
||||
}
|
||||
}
|
||||
//Test a large string > 65535 length
|
||||
|
||||
var buffer bytes.Buffer
|
||||
for i := 0; i < 0x00011170; i++ { //70,000 character string
|
||||
buffer.WriteString("a")
|
||||
}
|
||||
inp := buffer.String()
|
||||
want := "\x7a\x00\x01\x11\x70" + inp
|
||||
b := AppendString([]byte{}, inp)
|
||||
if got := string(b); got != want {
|
||||
t.Errorf("appendString(%q) = %#q, want %#q", inp, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendBytes(t *testing.T) {
|
||||
for _, tt := range encodeByteTests {
|
||||
b := AppendBytes([]byte{}, tt.plain)
|
||||
if got, want := string(b), tt.binary; got != want {
|
||||
t.Errorf("appendString(%q) = %#q, want %#q", tt.plain, got, want)
|
||||
}
|
||||
}
|
||||
//Test a large string > 65535 length
|
||||
|
||||
inp := []byte{}
|
||||
for i := 0; i < 0x00011170; i++ { //70,000 character string
|
||||
inp = append(inp, byte('a'))
|
||||
}
|
||||
want := "\x5a\x00\x01\x11\x70" + string(inp)
|
||||
b := AppendBytes([]byte{}, inp)
|
||||
if got := string(b); got != want {
|
||||
t.Errorf("appendString(%q) = %#q, want %#q", inp, got, want)
|
||||
}
|
||||
}
|
||||
func BenchmarkAppendString(b *testing.B) {
|
||||
tests := map[string]string{
|
||||
"NoEncoding": `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
|
||||
"EncodingFirst": `"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
|
||||
"EncodingMiddle": `aaaaaaaaaaaaaaaaaaaaaaaaa"aaaaaaaaaaaaaaaaaaaaaaaa`,
|
||||
"EncodingLast": `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
|
||||
"MultiBytesFirst": `❤️aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`,
|
||||
"MultiBytesMiddle": `aaaaaaaaaaaaaaaaaaaaaaaaa❤️aaaaaaaaaaaaaaaaaaaaaaaa`,
|
||||
"MultiBytesLast": `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa❤️`,
|
||||
}
|
||||
for name, str := range tests {
|
||||
b.Run(name, func(b *testing.B) {
|
||||
buf := make([]byte, 0, 120)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = AppendString(buf, str)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package cbor
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func appendIntegerTimestamp(dst []byte, t time.Time) []byte {
|
||||
major := majorTypeTags
|
||||
minor := additionalTypeTimestamp
|
||||
dst = append(dst, byte(major|minor))
|
||||
secs := t.Unix()
|
||||
var val uint64
|
||||
if secs < 0 {
|
||||
major = majorTypeNegativeInt
|
||||
val = uint64(-secs - 1)
|
||||
} else {
|
||||
major = majorTypeUnsignedInt
|
||||
val = uint64(secs)
|
||||
}
|
||||
dst = appendCborTypePrefix(dst, major, uint64(val))
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendFloatTimestamp(dst []byte, t time.Time) []byte {
|
||||
major := majorTypeTags
|
||||
minor := additionalTypeTimestamp
|
||||
dst = append(dst, byte(major|minor))
|
||||
secs := t.Unix()
|
||||
nanos := t.Nanosecond()
|
||||
var val float64
|
||||
val = float64(secs)*1.0 + float64(nanos)*1E-9
|
||||
return AppendFloat64(dst, val)
|
||||
}
|
||||
|
||||
// AppendTime encodes and adds a timestamp to the dst byte array.
|
||||
func AppendTime(dst []byte, t time.Time, unused string) []byte {
|
||||
utc := t.UTC()
|
||||
if utc.Nanosecond() == 0 {
|
||||
return appendIntegerTimestamp(dst, utc)
|
||||
}
|
||||
return appendFloatTimestamp(dst, utc)
|
||||
}
|
||||
|
||||
// AppendTimes encodes and adds an array of timestamps to the dst byte array.
|
||||
func AppendTimes(dst []byte, vals []time.Time, unused string) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
|
||||
for _, t := range vals {
|
||||
dst = AppendTime(dst, t, unused)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendDuration encodes and adds a duration to the dst byte array.
|
||||
// useInt field indicates whether to store the duration as seconds (integer) or
|
||||
// as seconds+nanoseconds (float).
|
||||
func AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
if useInt {
|
||||
return AppendInt64(dst, int64(d/unit))
|
||||
}
|
||||
return AppendFloat64(dst, float64(d)/float64(unit))
|
||||
}
|
||||
|
||||
// AppendDurations encodes and adds an array of durations to the dst byte array.
|
||||
// useInt field indicates whether to store the duration as seconds (integer) or
|
||||
// as seconds+nanoseconds (float).
|
||||
func AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, d := range vals {
|
||||
dst = AppendDuration(dst, d, unit, useInt)
|
||||
}
|
||||
return dst
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package cbor
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAppendTimeNow(t *testing.T) {
|
||||
tm := time.Now()
|
||||
s := AppendTime([]byte{}, tm, "unused")
|
||||
got := string(s)
|
||||
|
||||
tm1 := float64(tm.Unix()) + float64(tm.Nanosecond())*1E-9
|
||||
tm2 := math.Float64bits(tm1)
|
||||
var tm3 [8]byte
|
||||
for i := uint(0); i < 8; i++ {
|
||||
tm3[i] = byte(tm2 >> ((8 - i - 1) * 8))
|
||||
}
|
||||
want := append([]byte{0xc1, 0xfb}, tm3[:]...)
|
||||
if got != string(want) {
|
||||
t.Errorf("Appendtime(%s)=0x%s, want: 0x%s",
|
||||
"time.Now()", hex.EncodeToString(s),
|
||||
hex.EncodeToString(want))
|
||||
}
|
||||
}
|
||||
|
||||
var timeIntegerTestcases = []struct {
|
||||
txt string
|
||||
binary string
|
||||
rfcStr string
|
||||
}{
|
||||
{"2013-02-03T19:54:00-08:00", "\xc1\x1a\x51\x0f\x30\xd8", "2013-02-04T03:54:00Z"},
|
||||
{"1950-02-03T19:54:00-08:00", "\xc1\x3a\x25\x71\x93\xa7", "1950-02-04T03:54:00Z"},
|
||||
}
|
||||
|
||||
func TestAppendTimePastPresentInteger(t *testing.T) {
|
||||
for _, tt := range timeIntegerTestcases {
|
||||
tin, err := time.Parse(time.RFC3339, tt.txt)
|
||||
if err != nil {
|
||||
fmt.Println("Cannot parse input", tt.txt, ".. Skipping!", err)
|
||||
continue
|
||||
}
|
||||
b := AppendTime([]byte{}, tin, "unused")
|
||||
if got, want := string(b), tt.binary; got != want {
|
||||
t.Errorf("appendString(%s) = 0x%s, want 0x%s", tt.txt,
|
||||
hex.EncodeToString(b),
|
||||
hex.EncodeToString([]byte(want)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var timeFloatTestcases = []struct {
|
||||
rfcStr string
|
||||
out string
|
||||
}{
|
||||
{"2006-01-02T15:04:05.999999-08:00", "\xc1\xfb\x41\xd0\xee\x6c\x59\x7f\xff\xfc"},
|
||||
{"1956-01-02T15:04:05.999999-08:00", "\xc1\xfb\xc1\xba\x53\x81\x1a\x00\x00\x11"},
|
||||
}
|
||||
|
||||
func TestAppendTimePastPresentFloat(t *testing.T) {
|
||||
const timeFloatFmt = "2006-01-02T15:04:05.999999-07:00"
|
||||
for _, tt := range timeFloatTestcases {
|
||||
tin, err := time.Parse(timeFloatFmt, tt.rfcStr)
|
||||
if err != nil {
|
||||
fmt.Println("Cannot parse input", tt.rfcStr, ".. Skipping!")
|
||||
continue
|
||||
}
|
||||
b := AppendTime([]byte{}, tin, "unused")
|
||||
if got, want := string(b), tt.out; got != want {
|
||||
t.Errorf("appendString(%s) = 0x%s, want 0x%s", tt.rfcStr,
|
||||
hex.EncodeToString(b),
|
||||
hex.EncodeToString([]byte(want)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendTime(b *testing.B) {
|
||||
tests := map[string]string{
|
||||
"Integer": "Feb 3, 2013 at 7:54pm (PST)",
|
||||
"Float": "2006-01-02T15:04:05.999999-08:00",
|
||||
}
|
||||
const timeFloatFmt = "2006-01-02T15:04:05.999999-07:00"
|
||||
|
||||
for name, str := range tests {
|
||||
t, err := time.Parse(time.RFC3339, str)
|
||||
if err != nil {
|
||||
t, _ = time.Parse(timeFloatFmt, str)
|
||||
}
|
||||
b.Run(name, func(b *testing.B) {
|
||||
buf := make([]byte, 0, 100)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = AppendTime(buf, t, "unused")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,438 @@
|
|||
package cbor
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// AppendNull inserts a 'Nil' object into the dst byte array.
|
||||
func AppendNull(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeNull))
|
||||
}
|
||||
|
||||
// AppendBeginMarker inserts a map start into the dst byte array.
|
||||
func AppendBeginMarker(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeMap|additionalTypeInfiniteCount))
|
||||
}
|
||||
|
||||
// AppendEndMarker inserts a map end into the dst byte array.
|
||||
func AppendEndMarker(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeBreak))
|
||||
}
|
||||
|
||||
// AppendBool encodes and inserts a boolean value into the dst byte array.
|
||||
func AppendBool(dst []byte, val bool) []byte {
|
||||
b := additionalTypeBoolFalse
|
||||
if val {
|
||||
b = additionalTypeBoolTrue
|
||||
}
|
||||
return append(dst, byte(majorTypeSimpleAndFloat|b))
|
||||
}
|
||||
|
||||
// AppendBools encodes and inserts an array of boolean values into the dst byte array.
|
||||
func AppendBools(dst []byte, vals []bool) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendBool(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt encodes and inserts an integer value into the dst byte array.
|
||||
func AppendInt(dst []byte, val int) []byte {
|
||||
major := majorTypeUnsignedInt
|
||||
contentVal := val
|
||||
if val < 0 {
|
||||
major = majorTypeNegativeInt
|
||||
contentVal = -val - 1
|
||||
}
|
||||
if contentVal <= additionalMax {
|
||||
lb := byte(contentVal)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(contentVal))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInts encodes and inserts an array of integer values into the dst byte array.
|
||||
func AppendInts(dst []byte, vals []int) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt8 encodes and inserts an int8 value into the dst byte array.
|
||||
func AppendInt8(dst []byte, val int8) []byte {
|
||||
return AppendInt(dst, int(val))
|
||||
}
|
||||
|
||||
// AppendInts8 encodes and inserts an array of integer values into the dst byte array.
|
||||
func AppendInts8(dst []byte, vals []int8) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt(dst, int(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt16 encodes and inserts a int16 value into the dst byte array.
|
||||
func AppendInt16(dst []byte, val int16) []byte {
|
||||
return AppendInt(dst, int(val))
|
||||
}
|
||||
|
||||
// AppendInts16 encodes and inserts an array of int16 values into the dst byte array.
|
||||
func AppendInts16(dst []byte, vals []int16) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt(dst, int(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt32 encodes and inserts a int32 value into the dst byte array.
|
||||
func AppendInt32(dst []byte, val int32) []byte {
|
||||
return AppendInt(dst, int(val))
|
||||
}
|
||||
|
||||
// AppendInts32 encodes and inserts an array of int32 values into the dst byte array.
|
||||
func AppendInts32(dst []byte, vals []int32) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt(dst, int(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInt64 encodes and inserts a int64 value into the dst byte array.
|
||||
func AppendInt64(dst []byte, val int64) []byte {
|
||||
major := majorTypeUnsignedInt
|
||||
contentVal := val
|
||||
if val < 0 {
|
||||
major = majorTypeNegativeInt
|
||||
contentVal = -val - 1
|
||||
}
|
||||
if contentVal <= additionalMax {
|
||||
lb := byte(contentVal)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(contentVal))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInts64 encodes and inserts an array of int64 values into the dst byte array.
|
||||
func AppendInts64(dst []byte, vals []int64) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendInt64(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint encodes and inserts an unsigned integer value into the dst byte array.
|
||||
func AppendUint(dst []byte, val uint) []byte {
|
||||
return AppendInt64(dst, int64(val))
|
||||
}
|
||||
|
||||
// AppendUints encodes and inserts an array of unsigned integer values into the dst byte array.
|
||||
func AppendUints(dst []byte, vals []uint) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint8 encodes and inserts a unsigned int8 value into the dst byte array.
|
||||
func AppendUint8(dst []byte, val uint8) []byte {
|
||||
return AppendUint(dst, uint(val))
|
||||
}
|
||||
|
||||
// AppendUints8 encodes and inserts an array of uint8 values into the dst byte array.
|
||||
func AppendUints8(dst []byte, vals []uint8) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint8(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint16 encodes and inserts a uint16 value into the dst byte array.
|
||||
func AppendUint16(dst []byte, val uint16) []byte {
|
||||
return AppendUint(dst, uint(val))
|
||||
}
|
||||
|
||||
// AppendUints16 encodes and inserts an array of uint16 values into the dst byte array.
|
||||
func AppendUints16(dst []byte, vals []uint16) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint16(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint32 encodes and inserts a uint32 value into the dst byte array.
|
||||
func AppendUint32(dst []byte, val uint32) []byte {
|
||||
return AppendUint(dst, uint(val))
|
||||
}
|
||||
|
||||
// AppendUints32 encodes and inserts an array of uint32 values into the dst byte array.
|
||||
func AppendUints32(dst []byte, vals []uint32) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint32(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUint64 encodes and inserts a uint64 value into the dst byte array.
|
||||
func AppendUint64(dst []byte, val uint64) []byte {
|
||||
major := majorTypeUnsignedInt
|
||||
contentVal := val
|
||||
if contentVal <= additionalMax {
|
||||
lb := byte(contentVal)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(contentVal))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendUints64 encodes and inserts an array of uint64 values into the dst byte array.
|
||||
func AppendUints64(dst []byte, vals []uint64) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendUint64(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloat32 encodes and inserts a single precision float value into the dst byte array.
|
||||
func AppendFloat32(dst []byte, val float32) []byte {
|
||||
switch {
|
||||
case math.IsNaN(float64(val)):
|
||||
return append(dst, "\xfa\x7f\xc0\x00\x00"...)
|
||||
case math.IsInf(float64(val), 1):
|
||||
return append(dst, "\xfa\x7f\x80\x00\x00"...)
|
||||
case math.IsInf(float64(val), -1):
|
||||
return append(dst, "\xfa\xff\x80\x00\x00"...)
|
||||
}
|
||||
major := majorTypeSimpleAndFloat
|
||||
subType := additionalTypeFloat32
|
||||
n := math.Float32bits(val)
|
||||
var buf [4]byte
|
||||
for i := uint(0); i < 4; i++ {
|
||||
buf[i] = byte(n >> ((3 - i) * 8))
|
||||
}
|
||||
return append(append(dst, byte(major|subType)), buf[0], buf[1], buf[2], buf[3])
|
||||
}
|
||||
|
||||
// AppendFloats32 encodes and inserts an array of single precision float value into the dst byte array.
|
||||
func AppendFloats32(dst []byte, vals []float32) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendFloat32(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloat64 encodes and inserts a double precision float value into the dst byte array.
|
||||
func AppendFloat64(dst []byte, val float64) []byte {
|
||||
switch {
|
||||
case math.IsNaN(val):
|
||||
return append(dst, "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"...)
|
||||
case math.IsInf(val, 1):
|
||||
return append(dst, "\xfb\x7f\xf0\x00\x00\x00\x00\x00\x00"...)
|
||||
case math.IsInf(val, -1):
|
||||
return append(dst, "\xfb\xff\xf0\x00\x00\x00\x00\x00\x00"...)
|
||||
}
|
||||
major := majorTypeSimpleAndFloat
|
||||
subType := additionalTypeFloat64
|
||||
n := math.Float64bits(val)
|
||||
dst = append(dst, byte(major|subType))
|
||||
for i := uint(1); i <= 8; i++ {
|
||||
b := byte(n >> ((8 - i) * 8))
|
||||
dst = append(dst, b)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendFloats64 encodes and inserts an array of double precision float values into the dst byte array.
|
||||
func AppendFloats64(dst []byte, vals []float64) []byte {
|
||||
major := majorTypeArray
|
||||
l := len(vals)
|
||||
if l == 0 {
|
||||
return AppendArrayEnd(AppendArrayStart(dst))
|
||||
}
|
||||
if l <= additionalMax {
|
||||
lb := byte(l)
|
||||
dst = append(dst, byte(major|lb))
|
||||
} else {
|
||||
dst = appendCborTypePrefix(dst, major, uint64(l))
|
||||
}
|
||||
for _, v := range vals {
|
||||
dst = AppendFloat64(dst, v)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// AppendInterface takes an arbitrary object and converts it to JSON and embeds it dst.
|
||||
func AppendInterface(dst []byte, i interface{}) []byte {
|
||||
marshaled, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return AppendString(dst, fmt.Sprintf("marshaling error: %v", err))
|
||||
}
|
||||
return AppendEmbeddedJSON(dst, marshaled)
|
||||
}
|
||||
|
||||
// AppendObjectData takes an object in form of a byte array and appends to dst.
|
||||
func AppendObjectData(dst []byte, o []byte) []byte {
|
||||
return append(dst, o...)
|
||||
}
|
||||
|
||||
// AppendArrayStart adds markers to indicate the start of an array.
|
||||
func AppendArrayStart(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeArray|additionalTypeInfiniteCount))
|
||||
}
|
||||
|
||||
// AppendArrayEnd adds markers to indicate the end of an array.
|
||||
func AppendArrayEnd(dst []byte) []byte {
|
||||
return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeBreak))
|
||||
}
|
||||
|
||||
// AppendArrayDelim adds markers to indicate end of a particular array element.
|
||||
func AppendArrayDelim(dst []byte) []byte {
|
||||
//No delimiters needed in cbor
|
||||
return dst
|
||||
}
|
||||
|
||||
func AppendHex (dst []byte, val []byte) []byte {
|
||||
dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16))
|
||||
dst = append(dst, byte(additionalTypeTagHexString>>8))
|
||||
dst = append(dst, byte(additionalTypeTagHexString&0xff))
|
||||
return AppendBytes(dst, val)
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package cbor
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAppendNull(t *testing.T) {
|
||||
s := AppendNull([]byte{})
|
||||
got := string(s)
|
||||
want := "\xf6"
|
||||
if got != want {
|
||||
t.Errorf("appendNull() = 0x%s, want: 0x%s", hex.EncodeToString(s),
|
||||
hex.EncodeToString([]byte(want)))
|
||||
}
|
||||
}
|
||||
|
||||
var booleanTestCases = []struct {
|
||||
val bool
|
||||
binary string
|
||||
json string
|
||||
}{
|
||||
{true, "\xf5", "true"},
|
||||
{false, "\xf4", "false"},
|
||||
}
|
||||
|
||||
func TestAppendBool(t *testing.T) {
|
||||
for _, tc := range booleanTestCases {
|
||||
s := AppendBool([]byte{}, tc.val)
|
||||
got := string(s)
|
||||
if got != tc.binary {
|
||||
t.Errorf("AppendBool(%s)=0x%s, want: 0x%s",
|
||||
tc.json, hex.EncodeToString(s),
|
||||
hex.EncodeToString([]byte(tc.binary)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var booleanArrayTestCases = []struct {
|
||||
val []bool
|
||||
binary string
|
||||
json string
|
||||
}{
|
||||
{[]bool{true, false, true}, "\x83\xf5\xf4\xf5", "[true,false,true]"},
|
||||
{[]bool{true, false, false, true, false, true}, "\x86\xf5\xf4\xf4\xf5\xf4\xf5", "[true,false,false,true,false,true]"},
|
||||
}
|
||||
|
||||
func TestAppendBoolArray(t *testing.T) {
|
||||
for _, tc := range booleanArrayTestCases {
|
||||
s := AppendBools([]byte{}, tc.val)
|
||||
got := string(s)
|
||||
if got != tc.binary {
|
||||
t.Errorf("AppendBools(%s)=0x%s, want: 0x%s",
|
||||
tc.json, hex.EncodeToString(s),
|
||||
hex.EncodeToString([]byte(tc.binary)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var integerTestCases = []struct {
|
||||
val int
|
||||
binary string
|
||||
}{
|
||||
// Value included in the type.
|
||||
{0, "\x00"},
|
||||
{1, "\x01"},
|
||||
{2, "\x02"},
|
||||
{3, "\x03"},
|
||||
{8, "\x08"},
|
||||
{9, "\x09"},
|
||||
{10, "\x0a"},
|
||||
{22, "\x16"},
|
||||
{23, "\x17"},
|
||||
// Value in 1 byte.
|
||||
{24, "\x18\x18"},
|
||||
{25, "\x18\x19"},
|
||||
{26, "\x18\x1a"},
|
||||
{100, "\x18\x64"},
|
||||
{254, "\x18\xfe"},
|
||||
{255, "\x18\xff"},
|
||||
// Value in 2 bytes.
|
||||
{256, "\x19\x01\x00"},
|
||||
{257, "\x19\x01\x01"},
|
||||
{1000, "\x19\x03\xe8"},
|
||||
{0xFFFF, "\x19\xff\xff"},
|
||||
// Value in 4 bytes.
|
||||
{0x10000, "\x1a\x00\x01\x00\x00"},
|
||||
{0xFFFFFFFE, "\x1a\xff\xff\xff\xfe"},
|
||||
{1000000, "\x1a\x00\x0f\x42\x40"},
|
||||
// Value in 8 bytes.
|
||||
{0xabcd100000000, "\x1b\x00\x0a\xbc\xd1\x00\x00\x00\x00"},
|
||||
{1000000000000, "\x1b\x00\x00\x00\xe8\xd4\xa5\x10\x00"},
|
||||
// Negative number test cases.
|
||||
// Value included in the type.
|
||||
{-1, "\x20"},
|
||||
{-2, "\x21"},
|
||||
{-3, "\x22"},
|
||||
{-10, "\x29"},
|
||||
{-21, "\x34"},
|
||||
{-22, "\x35"},
|
||||
{-23, "\x36"},
|
||||
{-24, "\x37"},
|
||||
// Value in 1 byte.
|
||||
{-25, "\x38\x18"},
|
||||
{-26, "\x38\x19"},
|
||||
{-100, "\x38\x63"},
|
||||
{-254, "\x38\xfd"},
|
||||
{-255, "\x38\xfe"},
|
||||
{-256, "\x38\xff"},
|
||||
// Value in 2 bytes.
|
||||
{-257, "\x39\x01\x00"},
|
||||
{-258, "\x39\x01\x01"},
|
||||
{-1000, "\x39\x03\xe7"},
|
||||
// Value in 4 bytes.
|
||||
{-0x10001, "\x3a\x00\x01\x00\x00"},
|
||||
{-0xFFFFFFFE, "\x3a\xff\xff\xff\xfd"},
|
||||
{-1000000, "\x3a\x00\x0f\x42\x3f"},
|
||||
// Value in 8 bytes.
|
||||
{-0xabcd100000001, "\x3b\x00\x0a\xbc\xd1\x00\x00\x00\x00"},
|
||||
{-1000000000001, "\x3b\x00\x00\x00\xe8\xd4\xa5\x10\x00"},
|
||||
}
|
||||
|
||||
func TestAppendInt(t *testing.T) {
|
||||
for _, tc := range integerTestCases {
|
||||
s := AppendInt([]byte{}, tc.val)
|
||||
got := string(s)
|
||||
if got != tc.binary {
|
||||
t.Errorf("AppendInt(0x%x)=0x%s, want: 0x%s",
|
||||
tc.val, hex.EncodeToString(s),
|
||||
hex.EncodeToString([]byte(tc.binary)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var integerArrayTestCases = []struct {
|
||||
val []int
|
||||
binary string
|
||||
json string
|
||||
}{
|
||||
{[]int{-1, 0, 200, 20}, "\x84\x20\x00\x18\xc8\x14", "[-1,0,200,20]"},
|
||||
{[]int{-200, -10, 200, 400}, "\x84\x38\xc7\x29\x18\xc8\x19\x01\x90", "[-200,-10,200,400]"},
|
||||
{[]int{1, 2, 3}, "\x83\x01\x02\x03", "[1,2,3]"},
|
||||
{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25},
|
||||
"\x98\x19\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x18\x18\x19",
|
||||
"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]"},
|
||||
}
|
||||
|
||||
func TestAppendIntArray(t *testing.T) {
|
||||
for _, tc := range integerArrayTestCases {
|
||||
s := AppendInts([]byte{}, tc.val)
|
||||
got := string(s)
|
||||
if got != tc.binary {
|
||||
t.Errorf("AppendInts(%s)=0x%s, want: 0x%s",
|
||||
tc.json, hex.EncodeToString(s),
|
||||
hex.EncodeToString([]byte(tc.binary)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var float32TestCases = []struct {
|
||||
val float32
|
||||
binary string
|
||||
}{
|
||||
{0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{-0.0, "\xfa\x00\x00\x00\x00"},
|
||||
{1.0, "\xfa\x3f\x80\x00\x00"},
|
||||
{1.5, "\xfa\x3f\xc0\x00\x00"},
|
||||
{65504.0, "\xfa\x47\x7f\xe0\x00"},
|
||||
{-4.0, "\xfa\xc0\x80\x00\x00"},
|
||||
{0.00006103515625, "\xfa\x38\x80\x00\x00"},
|
||||
}
|
||||
|
||||
func TestAppendFloat32(t *testing.T) {
|
||||
for _, tc := range float32TestCases {
|
||||
s := AppendFloat32([]byte{}, tc.val)
|
||||
got := string(s)
|
||||
if got != tc.binary {
|
||||
t.Errorf("AppendFloat32(%f)=0x%s, want: 0x%s",
|
||||
tc.val, hex.EncodeToString(s),
|
||||
hex.EncodeToString([]byte(tc.binary)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendInt(b *testing.B) {
|
||||
type st struct {
|
||||
sz byte
|
||||
val int64
|
||||
}
|
||||
tests := map[string]st{
|
||||
"int-Positive": {sz: 0, val: 10000},
|
||||
"int-Negative": {sz: 0, val: -10000},
|
||||
"uint8": {sz: 1, val: 100},
|
||||
"uint16": {sz: 2, val: 0xfff},
|
||||
"uint32": {sz: 4, val: 0xffffff},
|
||||
"uint64": {sz: 8, val: 0xffffffffff},
|
||||
"int8": {sz: 21, val: -120},
|
||||
"int16": {sz: 22, val: -1200},
|
||||
"int32": {sz: 23, val: 32000},
|
||||
"int64": {sz: 24, val: 0xffffffffff},
|
||||
}
|
||||
for name, str := range tests {
|
||||
b.Run(name, func(b *testing.B) {
|
||||
buf := make([]byte, 0, 100)
|
||||
for i := 0; i < b.N; i++ {
|
||||
switch str.sz {
|
||||
case 0:
|
||||
_ = AppendInt(buf, int(str.val))
|
||||
case 1:
|
||||
_ = AppendUint8(buf, uint8(str.val))
|
||||
case 2:
|
||||
_ = AppendUint16(buf, uint16(str.val))
|
||||
case 4:
|
||||
_ = AppendUint32(buf, uint32(str.val))
|
||||
case 8:
|
||||
_ = AppendUint64(buf, uint64(str.val))
|
||||
case 21:
|
||||
_ = AppendInt8(buf, int8(str.val))
|
||||
case 22:
|
||||
_ = AppendInt16(buf, int16(str.val))
|
||||
case 23:
|
||||
_ = AppendInt32(buf, int32(str.val))
|
||||
case 24:
|
||||
_ = AppendInt64(buf, int64(str.val))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendFloat(b *testing.B) {
|
||||
type st struct {
|
||||
sz byte
|
||||
val float64
|
||||
}
|
||||
tests := map[string]st{
|
||||
"Float32": {sz: 4, val: 10000.12345},
|
||||
"Float64": {sz: 8, val: -10000.54321},
|
||||
}
|
||||
for name, str := range tests {
|
||||
b.Run(name, func(b *testing.B) {
|
||||
buf := make([]byte, 0, 100)
|
||||
for i := 0; i < b.N; i++ {
|
||||
switch str.sz {
|
||||
case 4:
|
||||
_ = AppendFloat32(buf, float32(str.val))
|
||||
case 8:
|
||||
_ = AppendFloat64(buf, str.val)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package json
|
|||
|
||||
// AppendKey appends a new key to the output JSON.
|
||||
func AppendKey(dst []byte, key string) []byte {
|
||||
if len(dst) > 1 {
|
||||
if len(dst) > 1 && dst[len(dst)-1] != '{' {
|
||||
dst = append(dst, ',')
|
||||
}
|
||||
dst = AppendString(dst, key)
|
||||
|
|
|
@ -332,3 +332,16 @@ func AppendInterface(dst []byte, i interface{}) []byte {
|
|||
}
|
||||
return append(dst, marshaled...)
|
||||
}
|
||||
|
||||
func AppendObjectData(dst []byte, o []byte) []byte {
|
||||
// Two conditions we want to put a ',' between existing content and
|
||||
// new content:
|
||||
// 1. new content starts with '{' - which shd be dropped OR
|
||||
// 2. existing content has already other fields
|
||||
if o[0] == '{' {
|
||||
o[0] = ','
|
||||
} else if len(dst) > 1 {
|
||||
dst = append(dst, ',')
|
||||
}
|
||||
return append(dst, o...)
|
||||
}
|
||||
|
|
7
log.go
7
log.go
|
@ -358,11 +358,8 @@ func (l *Logger) newEvent(level Level, done func(string)) *Event {
|
|||
if level != NoLevel {
|
||||
e.Str(LevelFieldName, level.String())
|
||||
}
|
||||
if len(l.context) > 0 {
|
||||
if len(e.buf) > 1 {
|
||||
e.buf = append(e.buf, ',')
|
||||
}
|
||||
e.buf = append(e.buf, l.context...)
|
||||
if l.context != nil && len(l.context) > 0 {
|
||||
e.buf = appendObjectData(e.buf, l.context)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build !binary_log
|
||||
|
||||
package log_test
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build !binary_log
|
||||
|
||||
package zerolog_test
|
||||
|
||||
import (
|
||||
|
@ -13,7 +15,6 @@ func ExampleNew() {
|
|||
log := zerolog.New(os.Stdout)
|
||||
|
||||
log.Info().Msg("hello world")
|
||||
|
||||
// Output: {"level":"info","message":"hello world"}
|
||||
}
|
||||
|
||||
|
|
55
log_test.go
55
log_test.go
|
@ -15,7 +15,7 @@ func TestLog(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Log().Msg("")
|
||||
if got, want := out.String(), "{}\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), "{}\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -24,7 +24,7 @@ func TestLog(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Log().Str("foo", "bar").Msg("")
|
||||
if got, want := out.String(), `{"foo":"bar"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"foo":"bar"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -36,7 +36,7 @@ func TestLog(t *testing.T) {
|
|||
Str("foo", "bar").
|
||||
Int("n", 123).
|
||||
Msg("")
|
||||
if got, want := out.String(), `{"foo":"bar","n":123}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"foo":"bar","n":123}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -47,7 +47,7 @@ func TestInfo(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Info().Msg("")
|
||||
if got, want := out.String(), `{"level":"info"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"info"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -56,7 +56,7 @@ func TestInfo(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Info().Str("foo", "bar").Msg("")
|
||||
if got, want := out.String(), `{"level":"info","foo":"bar"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"info","foo":"bar"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -68,7 +68,7 @@ func TestInfo(t *testing.T) {
|
|||
Str("foo", "bar").
|
||||
Int("n", 123).
|
||||
Msg("")
|
||||
if got, want := out.String(), `{"level":"info","foo":"bar","n":123}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"info","foo":"bar","n":123}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -101,7 +101,7 @@ func TestWith(t *testing.T) {
|
|||
caller := fmt.Sprintf("%s:%d", file, line+3)
|
||||
log := ctx.Caller().Logger()
|
||||
log.Log().Msg("")
|
||||
if got, want := out.String(), `{"string":"foo","bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"time":"0001-01-01T00:00:00Z","caller":"`+caller+`"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":"foo","bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"time":"0001-01-01T00:00:00Z","caller":"`+caller+`"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ func TestFieldsMap(t *testing.T) {
|
|||
"dur": 1 * time.Second,
|
||||
"time": time.Time{},
|
||||
}).Msg("")
|
||||
if got, want := out.String(), `{"bool":true,"bytes":"bar","dur":1000,"error":"some error","float32":11,"float64":12,"int":1,"int16":3,"int32":4,"int64":5,"int8":2,"nil":null,"string":"foo","time":"0001-01-01T00:00:00Z","uint":6,"uint16":8,"uint32":9,"uint64":10,"uint8":7}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"bool":true,"bytes":"bar","dur":1000,"error":"some error","float32":11,"float64":12,"int":1,"int16":3,"int32":4,"int64":5,"int8":2,"nil":null,"string":"foo","time":"0001-01-01T00:00:00Z","uint":6,"uint16":8,"uint32":9,"uint64":10,"uint8":7}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ func TestFieldsMapPnt(t *testing.T) {
|
|||
"dur": new(time.Duration),
|
||||
"time": new(time.Time),
|
||||
}).Msg("")
|
||||
if got, want := out.String(), `{"bool":false,"dur":0,"float32":0,"float64":0,"int":0,"int16":0,"int32":0,"int64":0,"int8":0,"string":"","time":"0001-01-01T00:00:00Z","uint":0,"uint16":0,"uint32":0,"uint64":0,"uint8":0}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"bool":false,"dur":0,"float32":0,"float64":0,"int":0,"int16":0,"int32":0,"int64":0,"int8":0,"string":"","time":"0001-01-01T00:00:00Z","uint":0,"uint16":0,"uint32":0,"uint64":0,"uint8":0}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ func TestFields(t *testing.T) {
|
|||
Time("time", time.Time{}).
|
||||
TimeDiff("diff", now, now.Add(-10*time.Second)).
|
||||
Msg("")
|
||||
if got, want := out.String(), `{"caller":"`+caller+`","string":"foo","bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","string":"foo","bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ func TestFieldsArrayEmpty(t *testing.T) {
|
|||
Durs("dur", []time.Duration{}).
|
||||
Times("time", []time.Time{}).
|
||||
Msg("")
|
||||
if got, want := out.String(), `{"string":[],"err":[],"bool":[],"int":[],"int8":[],"int16":[],"int32":[],"int64":[],"uint":[],"uint8":[],"uint16":[],"uint32":[],"uint64":[],"float32":[],"float64":[],"dur":[],"time":[]}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":[],"err":[],"bool":[],"int":[],"int8":[],"int16":[],"int32":[],"int64":[],"uint":[],"uint8":[],"uint16":[],"uint32":[],"uint64":[],"float32":[],"float64":[],"dur":[],"time":[]}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ func TestFieldsArraySingleElement(t *testing.T) {
|
|||
Durs("dur", []time.Duration{1 * time.Second}).
|
||||
Times("time", []time.Time{time.Time{}}).
|
||||
Msg("")
|
||||
if got, want := out.String(), `{"string":["foo"],"err":["some error"],"bool":[true],"int":[1],"int8":[2],"int16":[3],"int32":[4],"int64":[5],"uint":[6],"uint8":[7],"uint16":[8],"uint32":[9],"uint64":[10],"float32":[11],"float64":[12],"dur":[1000],"time":["0001-01-01T00:00:00Z"]}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":["foo"],"err":["some error"],"bool":[true],"int":[1],"int8":[2],"int16":[3],"int32":[4],"int64":[5],"uint":[6],"uint8":[7],"uint16":[8],"uint32":[9],"uint64":[10],"float32":[11],"float64":[12],"dur":[1000],"time":["0001-01-01T00:00:00Z"]}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ func TestFieldsArrayMultipleElement(t *testing.T) {
|
|||
Durs("dur", []time.Duration{1 * time.Second, 0}).
|
||||
Times("time", []time.Time{time.Time{}, time.Time{}}).
|
||||
Msg("")
|
||||
if got, want := out.String(), `{"string":["foo","bar"],"err":["some error",null],"bool":[true,false],"int":[1,0],"int8":[2,0],"int16":[3,0],"int32":[4,0],"int64":[5,0],"uint":[6,0],"uint8":[7,0],"uint16":[8,0],"uint32":[9,0],"uint64":[10,0],"float32":[11,0],"float64":[12,0],"dur":[1000,0],"time":["0001-01-01T00:00:00Z","0001-01-01T00:00:00Z"]}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":["foo","bar"],"err":["some error",null],"bool":[true,false],"int":[1,0],"int8":[2,0],"int16":[3,0],"int32":[4,0],"int64":[5,0],"uint":[6,0],"uint8":[7,0],"uint16":[8,0],"uint32":[9,0],"uint64":[10,0],"float32":[11,0],"float64":[12,0],"dur":[1000,0],"time":["0001-01-01T00:00:00Z","0001-01-01T00:00:00Z"]}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ func TestFieldsDisabled(t *testing.T) {
|
|||
Time("time", time.Time{}).
|
||||
TimeDiff("diff", now, now.Add(-10*time.Second)).
|
||||
Msg("")
|
||||
if got, want := out.String(), ""; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), ""; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ func TestMsgf(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Log().Msgf("one %s %.1f %d %v", "two", 3.4, 5, errors.New("six"))
|
||||
if got, want := out.String(), `{"message":"one two 3.4 5 six"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"message":"one two 3.4 5 six"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ func TestWithAndFieldsCombined(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).With().Str("f1", "val").Str("f2", "val").Logger()
|
||||
log.Log().Str("f3", "val").Msg("")
|
||||
if got, want := out.String(), `{"f1":"val","f2":"val","f3":"val"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"f1":"val","f2":"val","f3":"val"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ func TestLevel(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(Disabled)
|
||||
log.Info().Msg("test")
|
||||
if got, want := out.String(), ""; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), ""; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -342,7 +342,7 @@ func TestLevel(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(Disabled)
|
||||
log.Log().Msg("test")
|
||||
if got, want := out.String(), ""; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), ""; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -351,7 +351,7 @@ func TestLevel(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(InfoLevel)
|
||||
log.Log().Msg("test")
|
||||
if got, want := out.String(), `{"message":"test"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"message":"test"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -360,7 +360,7 @@ func TestLevel(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(PanicLevel)
|
||||
log.Log().Msg("test")
|
||||
if got, want := out.String(), `{"message":"test"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"message":"test"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -369,7 +369,7 @@ func TestLevel(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(InfoLevel)
|
||||
log.WithLevel(NoLevel).Msg("test")
|
||||
if got, want := out.String(), `{"message":"test"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"message":"test"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -378,7 +378,7 @@ func TestLevel(t *testing.T) {
|
|||
out := &bytes.Buffer{}
|
||||
log := New(out).Level(InfoLevel)
|
||||
log.Info().Msg("test")
|
||||
if got, want := out.String(), `{"level":"info","message":"test"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"info","message":"test"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
})
|
||||
|
@ -391,7 +391,7 @@ func TestSampling(t *testing.T) {
|
|||
log.Log().Int("i", 2).Msg("")
|
||||
log.Log().Int("i", 3).Msg("")
|
||||
log.Log().Int("i", 4).Msg("")
|
||||
if got, want := out.String(), "{\"i\":2}\n{\"i\":4}\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), "{\"i\":2}\n{\"i\":4}\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -408,6 +408,7 @@ func (lw *levelWriter) Write(p []byte) (int, error) {
|
|||
}
|
||||
|
||||
func (lw *levelWriter) WriteLevel(lvl Level, p []byte) (int, error) {
|
||||
p = decodeIfBinaryToBytes(p)
|
||||
lw.ops = append(lw.ops, struct {
|
||||
l Level
|
||||
p string
|
||||
|
@ -465,7 +466,7 @@ func TestContextTimestamp(t *testing.T) {
|
|||
log := New(out).With().Timestamp().Str("foo", "bar").Logger()
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
if got, want := out.String(), `{"foo":"bar","time":"2001-02-03T04:05:06Z","message":"hello world"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"foo":"bar","time":"2001-02-03T04:05:06Z","message":"hello world"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +482,7 @@ func TestEventTimestamp(t *testing.T) {
|
|||
log := New(out).With().Str("foo", "bar").Logger()
|
||||
log.Log().Timestamp().Msg("hello world")
|
||||
|
||||
if got, want := out.String(), `{"foo":"bar","time":"2001-02-03T04:05:06Z","message":"hello world"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"foo":"bar","time":"2001-02-03T04:05:06Z","message":"hello world"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -492,7 +493,7 @@ func TestOutputWithoutTimestamp(t *testing.T) {
|
|||
log := New(ignoredOut).Output(out).With().Str("foo", "bar").Logger()
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
if got, want := out.String(), `{"foo":"bar","message":"hello world"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"foo":"bar","message":"hello world"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +510,7 @@ func TestOutputWithTimestamp(t *testing.T) {
|
|||
log := New(ignoredOut).Output(out).With().Timestamp().Str("foo", "bar").Logger()
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
if got, want := out.String(), `{"foo":"bar","time":"2001-02-03T04:05:06Z","message":"hello world"}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"foo":"bar","time":"2001-02-03T04:05:06Z","message":"hello world"}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build !binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
// +build !windows
|
||||
// +build !binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// SyslogWriter is an interface matching a syslog.Writer struct.
|
||||
type SyslogWriter interface {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// +build !binary_log
|
||||
// +build !windows
|
||||
|
||||
package zerolog
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// +build !binary_log
|
||||
// +build !windows
|
||||
|
||||
package zerolog
|
||||
|
|
Loading…
Reference in New Issue