github.com/go-spring/spring-base@v1.1.3/log/field_encoder.go (about)

     1  /*
     2   * Copyright 2012-2019 the original author or authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      https://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package log
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"strconv"
    23  	"unicode/utf8"
    24  )
    25  
    26  // An Encoder is used to serialize strongly-typed Field.
    27  type Encoder interface {
    28  	AppendEncoderBegin() error
    29  	AppendEncoderEnd() error
    30  	AppendObjectBegin() error
    31  	AppendObjectEnd() error
    32  	AppendArrayBegin() error
    33  	AppendArrayEnd() error
    34  	AppendKey(key string) error
    35  	AppendBool(v bool) error
    36  	AppendInt64(v int64) error
    37  	AppendUint64(v uint64) error
    38  	AppendFloat64(v float64) error
    39  	AppendString(v string) error
    40  	AppendReflect(v interface{}) error
    41  }
    42  
    43  var (
    44  	_ Encoder = (*JSONEncoder)(nil)
    45  	_ Encoder = (*FlatEncoder)(nil)
    46  )
    47  
    48  type jsonToken int
    49  
    50  const (
    51  	jsonTokenUnknown jsonToken = iota
    52  	jsonTokenObjectBegin
    53  	jsonTokenObjectEnd
    54  	jsonTokenArrayBegin
    55  	jsonTokenArrayEnd
    56  	jsonTokenKey
    57  	jsonTokenValue
    58  )
    59  
    60  // JSONEncoder encodes Fields in json format.
    61  type JSONEncoder struct {
    62  	buf  *bytes.Buffer
    63  	last jsonToken
    64  }
    65  
    66  // NewJSONEncoder returns a new *JSONEncoder.
    67  func NewJSONEncoder(buf *bytes.Buffer) *JSONEncoder {
    68  	return &JSONEncoder{
    69  		buf:  buf,
    70  		last: jsonTokenUnknown,
    71  	}
    72  }
    73  
    74  // Reset resets the *JSONEncoder.
    75  func (enc *JSONEncoder) Reset() {
    76  	enc.last = jsonTokenUnknown
    77  }
    78  
    79  // AppendEncoderBegin appends an encoder begin character.
    80  func (enc *JSONEncoder) AppendEncoderBegin() error {
    81  	enc.last = jsonTokenObjectBegin
    82  	enc.buf.WriteByte('{')
    83  	return nil
    84  }
    85  
    86  // AppendEncoderEnd appends an encoder end character.
    87  func (enc *JSONEncoder) AppendEncoderEnd() error {
    88  	enc.last = jsonTokenObjectEnd
    89  	enc.buf.WriteByte('}')
    90  	return nil
    91  }
    92  
    93  // AppendObjectBegin appends a object begin character.
    94  func (enc *JSONEncoder) AppendObjectBegin() error {
    95  	enc.last = jsonTokenObjectBegin
    96  	enc.buf.WriteByte('{')
    97  	return nil
    98  }
    99  
   100  // AppendObjectEnd appends an object end character.
   101  func (enc *JSONEncoder) AppendObjectEnd() error {
   102  	enc.last = jsonTokenObjectEnd
   103  	enc.buf.WriteByte('}')
   104  	return nil
   105  }
   106  
   107  // AppendArrayBegin appends an array begin character.
   108  func (enc *JSONEncoder) AppendArrayBegin() error {
   109  	enc.last = jsonTokenArrayBegin
   110  	enc.buf.WriteByte('[')
   111  	return nil
   112  }
   113  
   114  // AppendArrayEnd appends an array end character.
   115  func (enc *JSONEncoder) AppendArrayEnd() error {
   116  	enc.last = jsonTokenArrayEnd
   117  	enc.buf.WriteByte(']')
   118  	return nil
   119  }
   120  
   121  func (enc *JSONEncoder) appendSeparator(curr jsonToken) {
   122  	switch curr {
   123  	case jsonTokenKey:
   124  		if enc.last == jsonTokenObjectEnd || enc.last == jsonTokenArrayEnd || enc.last == jsonTokenValue {
   125  			enc.buf.WriteByte(',')
   126  		}
   127  	case jsonTokenValue:
   128  		if enc.last == jsonTokenValue {
   129  			enc.buf.WriteByte(',')
   130  		}
   131  	}
   132  }
   133  
   134  // AppendKey appends a key.
   135  func (enc *JSONEncoder) AppendKey(key string) error {
   136  	enc.appendSeparator(jsonTokenKey)
   137  	enc.last = jsonTokenKey
   138  	enc.buf.WriteByte('"')
   139  	enc.safeAddString(key)
   140  	enc.buf.WriteByte('"')
   141  	enc.buf.WriteByte(':')
   142  	return nil
   143  }
   144  
   145  // AppendBool appends a bool.
   146  func (enc *JSONEncoder) AppendBool(v bool) error {
   147  	enc.appendSeparator(jsonTokenValue)
   148  	enc.last = jsonTokenValue
   149  	enc.buf.WriteString(strconv.FormatBool(v))
   150  	return nil
   151  }
   152  
   153  // AppendInt64 appends an int64.
   154  func (enc *JSONEncoder) AppendInt64(v int64) error {
   155  	enc.appendSeparator(jsonTokenValue)
   156  	enc.last = jsonTokenValue
   157  	enc.buf.WriteString(strconv.FormatInt(v, 10))
   158  	return nil
   159  }
   160  
   161  // AppendUint64 appends a uint64.
   162  func (enc *JSONEncoder) AppendUint64(u uint64) error {
   163  	enc.appendSeparator(jsonTokenValue)
   164  	enc.last = jsonTokenValue
   165  	enc.buf.WriteString(strconv.FormatUint(u, 10))
   166  	return nil
   167  }
   168  
   169  // AppendFloat64 appends a float64.
   170  func (enc *JSONEncoder) AppendFloat64(v float64) error {
   171  	enc.appendSeparator(jsonTokenValue)
   172  	enc.last = jsonTokenValue
   173  	enc.buf.WriteString(strconv.FormatFloat(v, 'f', -1, 64))
   174  	return nil
   175  }
   176  
   177  // AppendString appends a string.
   178  func (enc *JSONEncoder) AppendString(v string) error {
   179  	enc.appendSeparator(jsonTokenValue)
   180  	enc.last = jsonTokenValue
   181  	enc.buf.WriteByte('"')
   182  	enc.safeAddString(v)
   183  	enc.buf.WriteByte('"')
   184  	return nil
   185  }
   186  
   187  // AppendReflect appends an interface{}.
   188  func (enc *JSONEncoder) AppendReflect(v interface{}) error {
   189  	b, err := json.Marshal(v)
   190  	if err != nil {
   191  		return err
   192  	}
   193  	enc.appendSeparator(jsonTokenValue)
   194  	enc.last = jsonTokenValue
   195  	enc.buf.Write(b)
   196  	return nil
   197  }
   198  
   199  // safeAddString JSON-escapes a string and appends it to the buf.
   200  func (enc *JSONEncoder) safeAddString(s string) {
   201  	for i := 0; i < len(s); {
   202  		if enc.tryAddRuneSelf(s[i]) {
   203  			i++
   204  			continue
   205  		}
   206  		r, size := utf8.DecodeRuneInString(s[i:])
   207  		if enc.tryAddRuneError(r, size) {
   208  			i++
   209  			continue
   210  		}
   211  		enc.buf.WriteString(s[i : i+size])
   212  		i += size
   213  	}
   214  }
   215  
   216  // tryAddRuneSelf appends b if it's valid UTF-8 character represented in a single byte.
   217  func (enc *JSONEncoder) tryAddRuneSelf(b byte) bool {
   218  	const _hex = "0123456789abcdef"
   219  	if b >= utf8.RuneSelf {
   220  		return false
   221  	}
   222  	if 0x20 <= b && b != '\\' && b != '"' {
   223  		enc.buf.WriteByte(b)
   224  		return true
   225  	}
   226  	switch b {
   227  	case '\\', '"':
   228  		enc.buf.WriteByte('\\')
   229  		enc.buf.WriteByte(b)
   230  	case '\n':
   231  		enc.buf.WriteByte('\\')
   232  		enc.buf.WriteByte('n')
   233  	case '\r':
   234  		enc.buf.WriteByte('\\')
   235  		enc.buf.WriteByte('r')
   236  	case '\t':
   237  		enc.buf.WriteByte('\\')
   238  		enc.buf.WriteByte('t')
   239  	default:
   240  		// Encode bytes < 0x20, except for the escape sequences above.
   241  		enc.buf.WriteString(`\u00`)
   242  		enc.buf.WriteByte(_hex[b>>4])
   243  		enc.buf.WriteByte(_hex[b&0xF])
   244  	}
   245  	return true
   246  }
   247  
   248  func (enc *JSONEncoder) tryAddRuneError(r rune, size int) bool {
   249  	if r == utf8.RuneError && size == 1 {
   250  		enc.buf.WriteString(`\ufffd`)
   251  		return true
   252  	}
   253  	return false
   254  }
   255  
   256  // FlatEncoder encodes Fields in flat format.
   257  type FlatEncoder struct {
   258  	buf         *bytes.Buffer
   259  	separator   string
   260  	jsonEncoder *JSONEncoder
   261  	jsonDepth   int8
   262  	init        bool
   263  }
   264  
   265  // NewFlatEncoder return a new *FlatEncoder with separator.
   266  func NewFlatEncoder(buf *bytes.Buffer, separator string) *FlatEncoder {
   267  	return &FlatEncoder{
   268  		buf:         buf,
   269  		separator:   separator,
   270  		jsonEncoder: &JSONEncoder{buf: buf},
   271  	}
   272  }
   273  
   274  // AppendEncoderBegin appends an encoder begin character.
   275  func (enc *FlatEncoder) AppendEncoderBegin() error {
   276  	return nil
   277  }
   278  
   279  // AppendEncoderEnd appends an encoder end character.
   280  func (enc *FlatEncoder) AppendEncoderEnd() error {
   281  	return nil
   282  }
   283  
   284  // AppendObjectBegin appends a object begin character.
   285  func (enc *FlatEncoder) AppendObjectBegin() error {
   286  	enc.jsonDepth++
   287  	return enc.jsonEncoder.AppendObjectBegin()
   288  }
   289  
   290  // AppendObjectEnd appends an object end character.
   291  func (enc *FlatEncoder) AppendObjectEnd() error {
   292  	enc.jsonDepth--
   293  	err := enc.jsonEncoder.AppendObjectEnd()
   294  	if enc.jsonDepth == 0 {
   295  		enc.jsonEncoder.Reset()
   296  	}
   297  	return err
   298  }
   299  
   300  // AppendArrayBegin appends an array begin character.
   301  func (enc *FlatEncoder) AppendArrayBegin() error {
   302  	enc.jsonDepth++
   303  	return enc.jsonEncoder.AppendArrayBegin()
   304  }
   305  
   306  // AppendArrayEnd appends an array end character.
   307  func (enc *FlatEncoder) AppendArrayEnd() error {
   308  	enc.jsonDepth--
   309  	err := enc.jsonEncoder.AppendArrayEnd()
   310  	if enc.jsonDepth == 0 {
   311  		enc.jsonEncoder.Reset()
   312  	}
   313  	return err
   314  }
   315  
   316  // AppendKey appends a key.
   317  func (enc *FlatEncoder) AppendKey(key string) error {
   318  	if enc.jsonDepth > 0 {
   319  		return enc.jsonEncoder.AppendKey(key)
   320  	}
   321  	if enc.init {
   322  		enc.buf.WriteString(enc.separator)
   323  	}
   324  	enc.init = true
   325  	enc.buf.WriteString(key)
   326  	enc.buf.WriteByte('=')
   327  	return nil
   328  }
   329  
   330  // AppendBool appends a bool.
   331  func (enc *FlatEncoder) AppendBool(v bool) error {
   332  	if enc.jsonDepth > 0 {
   333  		return enc.jsonEncoder.AppendBool(v)
   334  	}
   335  	enc.buf.WriteString(strconv.FormatBool(v))
   336  	return nil
   337  }
   338  
   339  // AppendInt64 appends a int64.
   340  func (enc *FlatEncoder) AppendInt64(v int64) error {
   341  	if enc.jsonDepth > 0 {
   342  		return enc.jsonEncoder.AppendInt64(v)
   343  	}
   344  	enc.buf.WriteString(strconv.FormatInt(v, 10))
   345  	return nil
   346  }
   347  
   348  // AppendUint64 appends a uint64.
   349  func (enc *FlatEncoder) AppendUint64(v uint64) error {
   350  	if enc.jsonDepth > 0 {
   351  		return enc.jsonEncoder.AppendUint64(v)
   352  	}
   353  	enc.buf.WriteString(strconv.FormatUint(v, 10))
   354  	return nil
   355  }
   356  
   357  // AppendFloat64 appends a float64.
   358  func (enc *FlatEncoder) AppendFloat64(v float64) error {
   359  	if enc.jsonDepth > 0 {
   360  		return enc.jsonEncoder.AppendFloat64(v)
   361  	}
   362  	enc.buf.WriteString(strconv.FormatFloat(v, 'f', -1, 64))
   363  	return nil
   364  }
   365  
   366  // AppendString appends a string.
   367  func (enc *FlatEncoder) AppendString(v string) error {
   368  	if enc.jsonDepth > 0 {
   369  		return enc.jsonEncoder.AppendString(v)
   370  	}
   371  	enc.buf.WriteString(v)
   372  	return nil
   373  }
   374  
   375  // AppendReflect appends an interface{}.
   376  func (enc *FlatEncoder) AppendReflect(v interface{}) error {
   377  	if enc.jsonDepth > 0 {
   378  		return enc.jsonEncoder.AppendReflect(v)
   379  	}
   380  	b, err := json.Marshal(v)
   381  	if err != nil {
   382  		return err
   383  	}
   384  	enc.buf.Write(b)
   385  	return nil
   386  }