package json import "unicode/utf8" // AppendBytes is a mirror of appendString with []byte arg func (Encoder) AppendBytes(dst, s []byte) []byte { dst = append(dst, '"') for i := 0; i < len(s); i++ { if !noEscapeTable[s[i]] { dst = appendBytesComplex(dst, s, i) return append(dst, '"') } } dst = append(dst, s...) return append(dst, '"') } // AppendHex encodes the input bytes to a hex string and appends // the encoded string to the input byte slice. // // The operation loops though each byte and encodes it as hex using // the hex lookup table. func (Encoder) AppendHex(dst, s []byte) []byte { dst = append(dst, '"') for _, v := range s { dst = append(dst, hex[v>>4], hex[v&0x0f]) } return append(dst, '"') } // appendBytesComplex is a mirror of the appendStringComplex // with []byte arg func appendBytesComplex(dst, s []byte, i int) []byte { start := 0 for i < len(s) { b := s[i] if b >= utf8.RuneSelf { r, size := utf8.DecodeRune(s[i:]) if r == utf8.RuneError && size == 1 { if start < i { dst = append(dst, s[start:i]...) } dst = append(dst, `\ufffd`...) i += size start = i continue } i += size continue } if noEscapeTable[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 }