github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/encoding/hex/hex.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package hex implements hexadecimal encoding and decoding. 6 package hex 7 8 import ( 9 "errors" 10 "fmt" 11 "io" 12 "strings" 13 ) 14 15 const ( 16 hextable = "0123456789abcdef" 17 reverseHexTable = "" + 18 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 19 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 20 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 21 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff" + 22 "\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 23 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 24 "\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 25 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 26 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 27 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 28 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 29 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 30 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 31 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 32 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 33 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" 34 ) 35 36 // EncodedLen returns the length of an encoding of n source bytes. 37 // Specifically, it returns n * 2. 38 func EncodedLen(n int) int { return n * 2 } 39 40 // Encode encodes src into EncodedLen(len(src)) 41 // bytes of dst. As a convenience, it returns the number 42 // of bytes written to dst, but this value is always EncodedLen(len(src)). 43 // Encode implements hexadecimal encoding. 44 func Encode(dst, src []byte) int { 45 j := 0 46 for _, v := range src { 47 dst[j] = hextable[v>>4] 48 dst[j+1] = hextable[v&0x0f] 49 j += 2 50 } 51 return len(src) * 2 52 } 53 54 // ErrLength reports an attempt to decode an odd-length input 55 // using Decode or DecodeString. 56 // The stream-based Decoder returns io.ErrUnexpectedEOF instead of ErrLength. 57 var ErrLength = errors.New("encoding/hex: odd length hex string") 58 59 // InvalidByteError values describe errors resulting from an invalid byte in a hex string. 60 type InvalidByteError byte 61 62 func (e InvalidByteError) Error() string { 63 return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e)) 64 } 65 66 // DecodedLen returns the length of a decoding of x source bytes. 67 // Specifically, it returns x / 2. 68 func DecodedLen(x int) int { return x / 2 } 69 70 // Decode decodes src into DecodedLen(len(src)) bytes, 71 // returning the actual number of bytes written to dst. 72 // 73 // Decode expects that src contains only hexadecimal 74 // characters and that src has even length. 75 // If the input is malformed, Decode returns the number 76 // of bytes decoded before the error. 77 func Decode(dst, src []byte) (int, error) { 78 i, j := 0, 1 79 for ; j < len(src); j += 2 { 80 p := src[j-1] 81 q := src[j] 82 83 a := reverseHexTable[p] 84 b := reverseHexTable[q] 85 if a > 0x0f { 86 return i, InvalidByteError(p) 87 } 88 if b > 0x0f { 89 return i, InvalidByteError(q) 90 } 91 dst[i] = (a << 4) | b 92 i++ 93 } 94 if len(src)%2 == 1 { 95 // Check for invalid char before reporting bad length, 96 // since the invalid char (if present) is an earlier problem. 97 if reverseHexTable[src[j-1]] > 0x0f { 98 return i, InvalidByteError(src[j-1]) 99 } 100 return i, ErrLength 101 } 102 return i, nil 103 } 104 105 // EncodeToString returns the hexadecimal encoding of src. 106 func EncodeToString(src []byte) string { 107 dst := make([]byte, EncodedLen(len(src))) 108 Encode(dst, src) 109 return string(dst) 110 } 111 112 // DecodeString returns the bytes represented by the hexadecimal string s. 113 // 114 // DecodeString expects that src contains only hexadecimal 115 // characters and that src has even length. 116 // If the input is malformed, DecodeString returns 117 // the bytes decoded before the error. 118 func DecodeString(s string) ([]byte, error) { 119 src := []byte(s) 120 // We can use the source slice itself as the destination 121 // because the decode loop increments by one and then the 'seen' byte is not used anymore. 122 n, err := Decode(src, src) 123 return src[:n], err 124 } 125 126 // Dump returns a string that contains a hex dump of the given data. The format 127 // of the hex dump matches the output of `hexdump -C` on the command line. 128 func Dump(data []byte) string { 129 if len(data) == 0 { 130 return "" 131 } 132 133 var buf strings.Builder 134 // Dumper will write 79 bytes per complete 16 byte chunk, and at least 135 // 64 bytes for whatever remains. Round the allocation up, since only a 136 // maximum of 15 bytes will be wasted. 137 buf.Grow((1 + ((len(data) - 1) / 16)) * 79) 138 139 dumper := Dumper(&buf) 140 dumper.Write(data) 141 dumper.Close() 142 return buf.String() 143 } 144 145 // bufferSize is the number of hexadecimal characters to buffer in encoder and decoder. 146 const bufferSize = 1024 147 148 type encoder struct { 149 w io.Writer 150 err error 151 out [bufferSize]byte // output buffer 152 } 153 154 // NewEncoder returns an io.Writer that writes lowercase hexadecimal characters to w. 155 func NewEncoder(w io.Writer) io.Writer { 156 return &encoder{w: w} 157 } 158 159 func (e *encoder) Write(p []byte) (n int, err error) { 160 for len(p) > 0 && e.err == nil { 161 chunkSize := bufferSize / 2 162 if len(p) < chunkSize { 163 chunkSize = len(p) 164 } 165 166 var written int 167 encoded := Encode(e.out[:], p[:chunkSize]) 168 written, e.err = e.w.Write(e.out[:encoded]) 169 n += written / 2 170 p = p[chunkSize:] 171 } 172 return n, e.err 173 } 174 175 type decoder struct { 176 r io.Reader 177 err error 178 in []byte // input buffer (encoded form) 179 arr [bufferSize]byte // backing array for in 180 } 181 182 // NewDecoder returns an io.Reader that decodes hexadecimal characters from r. 183 // NewDecoder expects that r contain only an even number of hexadecimal characters. 184 func NewDecoder(r io.Reader) io.Reader { 185 return &decoder{r: r} 186 } 187 188 func (d *decoder) Read(p []byte) (n int, err error) { 189 // Fill internal buffer with sufficient bytes to decode 190 if len(d.in) < 2 && d.err == nil { 191 var numCopy, numRead int 192 numCopy = copy(d.arr[:], d.in) // Copies either 0 or 1 bytes 193 numRead, d.err = d.r.Read(d.arr[numCopy:]) 194 d.in = d.arr[:numCopy+numRead] 195 if d.err == io.EOF && len(d.in)%2 != 0 { 196 197 if a := reverseHexTable[d.in[len(d.in)-1]]; a > 0x0f { 198 d.err = InvalidByteError(d.in[len(d.in)-1]) 199 } else { 200 d.err = io.ErrUnexpectedEOF 201 } 202 } 203 } 204 205 // Decode internal buffer into output buffer 206 if numAvail := len(d.in) / 2; len(p) > numAvail { 207 p = p[:numAvail] 208 } 209 numDec, err := Decode(p, d.in[:len(p)*2]) 210 d.in = d.in[2*numDec:] 211 if err != nil { 212 d.in, d.err = nil, err // Decode error; discard input remainder 213 } 214 215 if len(d.in) < 2 { 216 return numDec, d.err // Only expose errors when buffer fully consumed 217 } 218 return numDec, nil 219 } 220 221 // Dumper returns a WriteCloser that writes a hex dump of all written data to 222 // w. The format of the dump matches the output of `hexdump -C` on the command 223 // line. 224 func Dumper(w io.Writer) io.WriteCloser { 225 return &dumper{w: w} 226 } 227 228 type dumper struct { 229 w io.Writer 230 rightChars [18]byte 231 buf [14]byte 232 used int // number of bytes in the current line 233 n uint // number of bytes, total 234 closed bool 235 } 236 237 func toChar(b byte) byte { 238 if b < 32 || b > 126 { 239 return '.' 240 } 241 return b 242 } 243 244 func (h *dumper) Write(data []byte) (n int, err error) { 245 if h.closed { 246 return 0, errors.New("encoding/hex: dumper closed") 247 } 248 249 // Output lines look like: 250 // 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=| 251 // ^ offset ^ extra space ^ ASCII of line. 252 for i := range data { 253 if h.used == 0 { 254 // At the beginning of a line we print the current 255 // offset in hex. 256 h.buf[0] = byte(h.n >> 24) 257 h.buf[1] = byte(h.n >> 16) 258 h.buf[2] = byte(h.n >> 8) 259 h.buf[3] = byte(h.n) 260 Encode(h.buf[4:], h.buf[:4]) 261 h.buf[12] = ' ' 262 h.buf[13] = ' ' 263 _, err = h.w.Write(h.buf[4:]) 264 if err != nil { 265 return 266 } 267 } 268 Encode(h.buf[:], data[i:i+1]) 269 h.buf[2] = ' ' 270 l := 3 271 if h.used == 7 { 272 // There's an additional space after the 8th byte. 273 h.buf[3] = ' ' 274 l = 4 275 } else if h.used == 15 { 276 // At the end of the line there's an extra space and 277 // the bar for the right column. 278 h.buf[3] = ' ' 279 h.buf[4] = '|' 280 l = 5 281 } 282 _, err = h.w.Write(h.buf[:l]) 283 if err != nil { 284 return 285 } 286 n++ 287 h.rightChars[h.used] = toChar(data[i]) 288 h.used++ 289 h.n++ 290 if h.used == 16 { 291 h.rightChars[16] = '|' 292 h.rightChars[17] = '\n' 293 _, err = h.w.Write(h.rightChars[:]) 294 if err != nil { 295 return 296 } 297 h.used = 0 298 } 299 } 300 return 301 } 302 303 func (h *dumper) Close() (err error) { 304 // See the comments in Write() for the details of this format. 305 if h.closed { 306 return 307 } 308 h.closed = true 309 if h.used == 0 { 310 return 311 } 312 h.buf[0] = ' ' 313 h.buf[1] = ' ' 314 h.buf[2] = ' ' 315 h.buf[3] = ' ' 316 h.buf[4] = '|' 317 nBytes := h.used 318 for h.used < 16 { 319 l := 3 320 if h.used == 7 { 321 l = 4 322 } else if h.used == 15 { 323 l = 5 324 } 325 _, err = h.w.Write(h.buf[:l]) 326 if err != nil { 327 return 328 } 329 h.used++ 330 } 331 h.rightChars[nBytes] = '|' 332 h.rightChars[nBytes+1] = '\n' 333 _, err = h.w.Write(h.rightChars[:nBytes+2]) 334 return 335 }