github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/msgfmt/jsonfmt/encoder_bytes.go (about)

     1  package jsonfmt
     2  
     3  import (
     4  	"unsafe"
     5  	"unicode/utf8"
     6  	"context"
     7  )
     8  
     9  type bytesEncoder struct {
    10  }
    11  
    12  func (encoder *bytesEncoder) Encode(ctx context.Context, space []byte, ptr unsafe.Pointer) []byte {
    13  	return WriteBytes(space, *(*[]byte)(ptr))
    14  }
    15  
    16  func WriteBytes(space []byte, s []byte) []byte {
    17  	space = append(space, '"')
    18  	// write string, the fast path, without utf8 and escape support
    19  	var i int
    20  	var c byte
    21  	for i, c = range s {
    22  		if c < utf8.RuneSelf && safeSet[c] {
    23  			space = append(space, c)
    24  		} else {
    25  			break
    26  		}
    27  	}
    28  	if i == len(s)-1 {
    29  		space = append(space, '"')
    30  		return space
    31  	}
    32  	return writeBytesSlowPath(space, s[i:])
    33  }
    34  
    35  func writeBytesSlowPath(space []byte, s []byte) []byte {
    36  	start := 0
    37  	// for the remaining parts, we process them char by char
    38  	var i int
    39  	var b byte
    40  	for i, b = range s {
    41  		if b >= utf8.RuneSelf {
    42  			space = append(space, '\\', '\\', 'x', hex[b>>4], hex[b&0xF])
    43  			start = i + 1
    44  			continue
    45  		}
    46  		if safeSet[b] {
    47  			continue
    48  		}
    49  		if start < i {
    50  			space = append(space, s[start:i]...)
    51  		}
    52  		switch b {
    53  		case '\\', '"':
    54  			space = append(space, '\\', b)
    55  		case '\n':
    56  			space = append(space, '\\', 'n')
    57  		case '\r':
    58  			space = append(space, '\\', 'r')
    59  		case '\t':
    60  			space = append(space, '\\', 't')
    61  		default:
    62  			// This encodes bytes < 0x20 except for \t, \n and \r.
    63  			space = append(space, '\\', '\\', 'x', hex[b>>4], hex[b&0xF])
    64  		}
    65  		start = i + 1
    66  	}
    67  	if start < len(s) {
    68  		space = append(space, s[start:]...)
    69  	}
    70  	return append(space, '"')
    71  }