github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/cford32/cford32.gno (about) 1 // Modified from the Go Source code for encoding/base32. 2 // Copyright 2009 The Go Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 // Package cford32 implements a base32-like encoding/decoding package, with the 7 // encoding scheme [specified by Douglas Crockford]. 8 // 9 // From the website, the requirements of said encoding scheme are to: 10 // 11 // - Be human readable and machine readable. 12 // - Be compact. Humans have difficulty in manipulating long strings of arbitrary symbols. 13 // - Be error resistant. Entering the symbols must not require keyboarding gymnastics. 14 // - Be pronounceable. Humans should be able to accurately transmit the symbols to other humans using a telephone. 15 // 16 // This is slightly different from a simple difference in encoding table from 17 // the Go's stdlib `encoding/base32`, as when decoding the characters i I l L are 18 // parsed as 1, and o O is parsed as 0. 19 // 20 // This package additionally provides ways to encode uint64's efficiently, 21 // as well as efficient encoding to a lowercase variation of the encoding. 22 // The encodings never use paddings. 23 // 24 // # Uint64 Encoding 25 // 26 // Aside from lower/uppercase encoding, there is a compact encoding, allowing 27 // to encode all values in [0,2^34), and the full encoding, allowing all 28 // values in [0,2^64). The compact encoding uses 7 characters, and the full 29 // encoding uses 13 characters. Both are parsed unambiguously by the Uint64 30 // decoder. 31 // 32 // The compact encodings have the first character between ['0','f'], while the 33 // full encoding's first character ranges between ['g','z']. Practically, in 34 // your usage of the package, you should consider which one to use and stick 35 // with it, while considering that the compact encoding, once it reaches 2^34, 36 // automatically switches to the full encoding. The properties of the generated 37 // strings are still maintained: for instance, any two encoded uint64s x,y 38 // consistently generated with the compact encoding, if the numeric value is 39 // x < y, will also be x < y in lexical ordering. However, values [0,2^34) have a 40 // "double encoding", which if mixed together lose the lexical ordering property. 41 // 42 // The Uint64 encoding is most useful for generating string versions of Uint64 43 // IDs. Practically, it allows you to retain sleek and compact IDs for your 44 // applcation for the first 2^34 (>17 billion) entities, while seamlessly 45 // rolling over to the full encoding should you exceed that. You are encouraged 46 // to use it unless you have a requirement or preferences for IDs consistently 47 // being always the same size. 48 // 49 // To use the cford32 encoding for IDs, you may want to consider using package 50 // [gno.land/p/demo/seqid]. 51 // 52 // [specified by Douglas Crockford]: https://www.crockford.com/base32.html 53 package cford32 54 55 import ( 56 "io" 57 "strconv" 58 ) 59 60 const ( 61 encTable = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" 62 encTableLower = "0123456789abcdefghjkmnpqrstvwxyz" 63 64 // each line is 16 bytes 65 decTable = "" + 66 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + // 00-0f 67 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + // 10-1f 68 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + // 20-2f 69 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff" + // 30-3f 70 "\xff\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x01\x12\x13\x01\x14\x15\x00" + // 40-4f 71 "\x16\x17\x18\x19\x1a\xff\x1b\x1c\x1d\x1e\x1f\xff\xff\xff\xff\xff" + // 50-5f 72 "\xff\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x01\x12\x13\x01\x14\x15\x00" + // 60-6f 73 "\x16\x17\x18\x19\x1a\xff\x1b\x1c\x1d\x1e\x1f\xff\xff\xff\xff\xff" + // 70-7f 74 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + // 80-ff (not ASCII) 75 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 76 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 77 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 78 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 79 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 80 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + 81 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" 82 ) 83 84 // CorruptInputError is returned by parsing functions when an invalid character 85 // in the input is found. The integer value represents the byte index where 86 // the error occurred. 87 // 88 // This is typically because the given character does not exist in the encoding. 89 type CorruptInputError int64 90 91 func (e CorruptInputError) Error() string { 92 return "illegal cford32 data at input byte " + strconv.FormatInt(int64(e), 10) 93 } 94 95 // Uint64 parses a cford32-encoded byte slice into a uint64. 96 // 97 // - The parser requires all provided character to be valid cford32 characters. 98 // - The parser disregards case. 99 // - If the first character is '0' <= c <= 'f', then the passed value is assumed 100 // encoded in the compact encoding, and must be 7 characters long. 101 // - If the first character is 'g' <= c <= 'z', then the passed value is 102 // assumed encoded in the full encoding, and must be 13 characters long. 103 // 104 // If any of these requirements fail, a CorruptInputError will be returned. 105 func Uint64(b []byte) (uint64, error) { 106 switch { 107 default: 108 return 0, CorruptInputError(0) 109 case len(b) == 7 && b[0] >= '0' && b[0] <= 'f': 110 decVals := [7]byte{ 111 decTable[b[0]], 112 decTable[b[1]], 113 decTable[b[2]], 114 decTable[b[3]], 115 decTable[b[4]], 116 decTable[b[5]], 117 decTable[b[6]], 118 } 119 for idx, v := range decVals { 120 if v >= 32 { 121 return 0, CorruptInputError(idx) 122 } 123 } 124 125 return 0 + 126 uint64(decVals[0])<<30 | 127 uint64(decVals[1])<<25 | 128 uint64(decVals[2])<<20 | 129 uint64(decVals[3])<<15 | 130 uint64(decVals[4])<<10 | 131 uint64(decVals[5])<<5 | 132 uint64(decVals[6]), nil 133 case len(b) == 13 && b[0] >= 'g' && b[0] <= 'z': 134 decVals := [13]byte{ 135 decTable[b[0]] & 0x0F, // disregard high bit 136 decTable[b[1]], 137 decTable[b[2]], 138 decTable[b[3]], 139 decTable[b[4]], 140 decTable[b[5]], 141 decTable[b[6]], 142 decTable[b[7]], 143 decTable[b[8]], 144 decTable[b[9]], 145 decTable[b[10]], 146 decTable[b[11]], 147 decTable[b[12]], 148 } 149 for idx, v := range decVals { 150 if v >= 32 { 151 return 0, CorruptInputError(idx) 152 } 153 } 154 155 return 0 + 156 uint64(decVals[0])<<60 | 157 uint64(decVals[1])<<55 | 158 uint64(decVals[2])<<50 | 159 uint64(decVals[3])<<45 | 160 uint64(decVals[4])<<40 | 161 uint64(decVals[5])<<35 | 162 uint64(decVals[6])<<30 | 163 uint64(decVals[7])<<25 | 164 uint64(decVals[8])<<20 | 165 uint64(decVals[9])<<15 | 166 uint64(decVals[10])<<10 | 167 uint64(decVals[11])<<5 | 168 uint64(decVals[12]), nil 169 } 170 } 171 172 const mask = 31 173 174 // PutUint64 returns a cford32-encoded byte slice. 175 func PutUint64(id uint64) [13]byte { 176 return [13]byte{ 177 encTable[id>>60&mask|0x10], // specify full encoding 178 encTable[id>>55&mask], 179 encTable[id>>50&mask], 180 encTable[id>>45&mask], 181 encTable[id>>40&mask], 182 encTable[id>>35&mask], 183 encTable[id>>30&mask], 184 encTable[id>>25&mask], 185 encTable[id>>20&mask], 186 encTable[id>>15&mask], 187 encTable[id>>10&mask], 188 encTable[id>>5&mask], 189 encTable[id&mask], 190 } 191 } 192 193 // PutUint64Lower returns a cford32-encoded byte array, swapping uppercase 194 // letters with lowercase. 195 // 196 // For more information on how the value is encoded, see [Uint64]. 197 func PutUint64Lower(id uint64) [13]byte { 198 return [13]byte{ 199 encTableLower[id>>60&mask|0x10], 200 encTableLower[id>>55&mask], 201 encTableLower[id>>50&mask], 202 encTableLower[id>>45&mask], 203 encTableLower[id>>40&mask], 204 encTableLower[id>>35&mask], 205 encTableLower[id>>30&mask], 206 encTableLower[id>>25&mask], 207 encTableLower[id>>20&mask], 208 encTableLower[id>>15&mask], 209 encTableLower[id>>10&mask], 210 encTableLower[id>>5&mask], 211 encTableLower[id&mask], 212 } 213 } 214 215 // PutCompact returns a cford32-encoded byte slice, using the compact 216 // representation of cford32 described in the package documentation where 217 // possible (all values of id < 1<<34). The lowercase encoding is used. 218 // 219 // The resulting byte slice will be 7 bytes long for all compact values, 220 // and 13 bytes long for 221 func PutCompact(id uint64) []byte { 222 return AppendCompact(id, nil) 223 } 224 225 // AppendCompact works like [PutCompact] but appends to the given byte slice 226 // instead of allocating one anew. 227 func AppendCompact(id uint64, b []byte) []byte { 228 const maxCompact = 1 << 34 229 if id < maxCompact { 230 return append(b, 231 encTableLower[id>>30&mask], 232 encTableLower[id>>25&mask], 233 encTableLower[id>>20&mask], 234 encTableLower[id>>15&mask], 235 encTableLower[id>>10&mask], 236 encTableLower[id>>5&mask], 237 encTableLower[id&mask], 238 ) 239 } 240 return append(b, 241 encTableLower[id>>60&mask|0x10], 242 encTableLower[id>>55&mask], 243 encTableLower[id>>50&mask], 244 encTableLower[id>>45&mask], 245 encTableLower[id>>40&mask], 246 encTableLower[id>>35&mask], 247 encTableLower[id>>30&mask], 248 encTableLower[id>>25&mask], 249 encTableLower[id>>20&mask], 250 encTableLower[id>>15&mask], 251 encTableLower[id>>10&mask], 252 encTableLower[id>>5&mask], 253 encTableLower[id&mask], 254 ) 255 } 256 257 func DecodedLen(n int) int { 258 return n/8*5 + n%8*5/8 259 } 260 261 func EncodedLen(n int) int { 262 return n/5*8 + (n%5*8+4)/5 263 } 264 265 // Encode encodes src using the encoding enc, 266 // writing [EncodedLen](len(src)) bytes to dst. 267 // 268 // The encoding does not contain any padding, unlike Go's base32. 269 func Encode(dst, src []byte) { 270 // Copied from encoding/base32/base32.go (go1.22) 271 if len(src) == 0 { 272 return 273 } 274 275 di, si := 0, 0 276 n := (len(src) / 5) * 5 277 for si < n { 278 // Combining two 32 bit loads allows the same code to be used 279 // for 32 and 64 bit platforms. 280 hi := uint32(src[si+0])<<24 | uint32(src[si+1])<<16 | uint32(src[si+2])<<8 | uint32(src[si+3]) 281 lo := hi<<8 | uint32(src[si+4]) 282 283 dst[di+0] = encTable[(hi>>27)&0x1F] 284 dst[di+1] = encTable[(hi>>22)&0x1F] 285 dst[di+2] = encTable[(hi>>17)&0x1F] 286 dst[di+3] = encTable[(hi>>12)&0x1F] 287 dst[di+4] = encTable[(hi>>7)&0x1F] 288 dst[di+5] = encTable[(hi>>2)&0x1F] 289 dst[di+6] = encTable[(lo>>5)&0x1F] 290 dst[di+7] = encTable[(lo)&0x1F] 291 292 si += 5 293 di += 8 294 } 295 296 // Add the remaining small block 297 remain := len(src) - si 298 if remain == 0 { 299 return 300 } 301 302 // Encode the remaining bytes in reverse order. 303 val := uint32(0) 304 switch remain { 305 case 4: 306 val |= uint32(src[si+3]) 307 dst[di+6] = encTable[val<<3&0x1F] 308 dst[di+5] = encTable[val>>2&0x1F] 309 fallthrough 310 case 3: 311 val |= uint32(src[si+2]) << 8 312 dst[di+4] = encTable[val>>7&0x1F] 313 fallthrough 314 case 2: 315 val |= uint32(src[si+1]) << 16 316 dst[di+3] = encTable[val>>12&0x1F] 317 dst[di+2] = encTable[val>>17&0x1F] 318 fallthrough 319 case 1: 320 val |= uint32(src[si+0]) << 24 321 dst[di+1] = encTable[val>>22&0x1F] 322 dst[di+0] = encTable[val>>27&0x1F] 323 } 324 } 325 326 // EncodeLower is like [Encode], but uses the lowercase 327 func EncodeLower(dst, src []byte) { 328 // Copied from encoding/base32/base32.go (go1.22) 329 if len(src) == 0 { 330 return 331 } 332 333 di, si := 0, 0 334 n := (len(src) / 5) * 5 335 for si < n { 336 // Combining two 32 bit loads allows the same code to be used 337 // for 32 and 64 bit platforms. 338 hi := uint32(src[si+0])<<24 | uint32(src[si+1])<<16 | uint32(src[si+2])<<8 | uint32(src[si+3]) 339 lo := hi<<8 | uint32(src[si+4]) 340 341 dst[di+0] = encTableLower[(hi>>27)&0x1F] 342 dst[di+1] = encTableLower[(hi>>22)&0x1F] 343 dst[di+2] = encTableLower[(hi>>17)&0x1F] 344 dst[di+3] = encTableLower[(hi>>12)&0x1F] 345 dst[di+4] = encTableLower[(hi>>7)&0x1F] 346 dst[di+5] = encTableLower[(hi>>2)&0x1F] 347 dst[di+6] = encTableLower[(lo>>5)&0x1F] 348 dst[di+7] = encTableLower[(lo)&0x1F] 349 350 si += 5 351 di += 8 352 } 353 354 // Add the remaining small block 355 remain := len(src) - si 356 if remain == 0 { 357 return 358 } 359 360 // Encode the remaining bytes in reverse order. 361 val := uint32(0) 362 switch remain { 363 case 4: 364 val |= uint32(src[si+3]) 365 dst[di+6] = encTableLower[val<<3&0x1F] 366 dst[di+5] = encTableLower[val>>2&0x1F] 367 fallthrough 368 case 3: 369 val |= uint32(src[si+2]) << 8 370 dst[di+4] = encTableLower[val>>7&0x1F] 371 fallthrough 372 case 2: 373 val |= uint32(src[si+1]) << 16 374 dst[di+3] = encTableLower[val>>12&0x1F] 375 dst[di+2] = encTableLower[val>>17&0x1F] 376 fallthrough 377 case 1: 378 val |= uint32(src[si+0]) << 24 379 dst[di+1] = encTableLower[val>>22&0x1F] 380 dst[di+0] = encTableLower[val>>27&0x1F] 381 } 382 } 383 384 // AppendEncode appends the cford32 encoded src to dst 385 // and returns the extended buffer. 386 func AppendEncode(dst, src []byte) []byte { 387 n := EncodedLen(len(src)) 388 dst = grow(dst, n) 389 Encode(dst[len(dst):][:n], src) 390 return dst[:len(dst)+n] 391 } 392 393 // AppendEncodeLower appends the lowercase cford32 encoded src to dst 394 // and returns the extended buffer. 395 func AppendEncodeLower(dst, src []byte) []byte { 396 n := EncodedLen(len(src)) 397 dst = grow(dst, n) 398 EncodeLower(dst[len(dst):][:n], src) 399 return dst[:len(dst)+n] 400 } 401 402 func grow(s []byte, n int) []byte { 403 // slices.Grow 404 if n -= cap(s) - len(s); n > 0 { 405 news := make([]byte, cap(s)+n) 406 copy(news[:cap(s)], s[:cap(s)]) 407 return news[:len(s)] 408 } 409 return s 410 } 411 412 // EncodeToString returns the cford32 encoding of src. 413 func EncodeToString(src []byte) string { 414 buf := make([]byte, EncodedLen(len(src))) 415 Encode(buf, src) 416 return string(buf) 417 } 418 419 // EncodeToStringLower returns the cford32 lowercase encoding of src. 420 func EncodeToStringLower(src []byte) string { 421 buf := make([]byte, EncodedLen(len(src))) 422 EncodeLower(buf, src) 423 return string(buf) 424 } 425 426 func decode(dst, src []byte) (n int, err error) { 427 dsti := 0 428 olen := len(src) 429 430 for len(src) > 0 { 431 // Decode quantum using the base32 alphabet 432 var dbuf [8]byte 433 dlen := 8 434 435 for j := 0; j < 8; { 436 if len(src) == 0 { 437 // We have reached the end and are not expecting any padding 438 dlen = j 439 break 440 } 441 in := src[0] 442 src = src[1:] 443 dbuf[j] = decTable[in] 444 if dbuf[j] == 0xFF { 445 return n, CorruptInputError(olen - len(src) - 1) 446 } 447 j++ 448 } 449 450 // Pack 8x 5-bit source blocks into 5 byte destination 451 // quantum 452 switch dlen { 453 case 8: 454 dst[dsti+4] = dbuf[6]<<5 | dbuf[7] 455 n++ 456 fallthrough 457 case 7: 458 dst[dsti+3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3 459 n++ 460 fallthrough 461 case 5: 462 dst[dsti+2] = dbuf[3]<<4 | dbuf[4]>>1 463 n++ 464 fallthrough 465 case 4: 466 dst[dsti+1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4 467 n++ 468 fallthrough 469 case 2: 470 dst[dsti+0] = dbuf[0]<<3 | dbuf[1]>>2 471 n++ 472 } 473 dsti += 5 474 } 475 return n, nil 476 } 477 478 type encoder struct { 479 err error 480 w io.Writer 481 enc func(dst, src []byte) 482 buf [5]byte // buffered data waiting to be encoded 483 nbuf int // number of bytes in buf 484 out [1024]byte // output buffer 485 } 486 487 func NewEncoder(w io.Writer) io.WriteCloser { 488 return &encoder{w: w, enc: Encode} 489 } 490 491 func NewEncoderLower(w io.Writer) io.WriteCloser { 492 return &encoder{w: w, enc: EncodeLower} 493 } 494 495 func (e *encoder) Write(p []byte) (n int, err error) { 496 if e.err != nil { 497 return 0, e.err 498 } 499 500 // Leading fringe. 501 if e.nbuf > 0 { 502 var i int 503 for i = 0; i < len(p) && e.nbuf < 5; i++ { 504 e.buf[e.nbuf] = p[i] 505 e.nbuf++ 506 } 507 n += i 508 p = p[i:] 509 if e.nbuf < 5 { 510 return 511 } 512 e.enc(e.out[0:], e.buf[0:]) 513 if _, e.err = e.w.Write(e.out[0:8]); e.err != nil { 514 return n, e.err 515 } 516 e.nbuf = 0 517 } 518 519 // Large interior chunks. 520 for len(p) >= 5 { 521 nn := len(e.out) / 8 * 5 522 if nn > len(p) { 523 nn = len(p) 524 nn -= nn % 5 525 } 526 e.enc(e.out[0:], p[0:nn]) 527 if _, e.err = e.w.Write(e.out[0 : nn/5*8]); e.err != nil { 528 return n, e.err 529 } 530 n += nn 531 p = p[nn:] 532 } 533 534 // Trailing fringe. 535 copy(e.buf[:], p) 536 e.nbuf = len(p) 537 n += len(p) 538 return 539 } 540 541 // Close flushes any pending output from the encoder. 542 // It is an error to call Write after calling Close. 543 func (e *encoder) Close() error { 544 // If there's anything left in the buffer, flush it out 545 if e.err == nil && e.nbuf > 0 { 546 e.enc(e.out[0:], e.buf[0:e.nbuf]) 547 encodedLen := EncodedLen(e.nbuf) 548 e.nbuf = 0 549 _, e.err = e.w.Write(e.out[0:encodedLen]) 550 } 551 return e.err 552 } 553 554 // Decode decodes src using cford32. It writes at most 555 // [DecodedLen](len(src)) bytes to dst and returns the number of bytes 556 // written. If src contains invalid cford32 data, it will return the 557 // number of bytes successfully written and [CorruptInputError]. 558 // Newline characters (\r and \n) are ignored. 559 func Decode(dst, src []byte) (n int, err error) { 560 buf := make([]byte, len(src)) 561 l := stripNewlines(buf, src) 562 return decode(dst, buf[:l]) 563 } 564 565 // AppendDecode appends the cford32 decoded src to dst 566 // and returns the extended buffer. 567 // If the input is malformed, it returns the partially decoded src and an error. 568 func AppendDecode(dst, src []byte) ([]byte, error) { 569 n := DecodedLen(len(src)) 570 571 dst = grow(dst, n) 572 dstsl := dst[len(dst) : len(dst)+n] 573 n, err := Decode(dstsl, src) 574 return dst[:len(dst)+n], err 575 } 576 577 // DecodeString returns the bytes represented by the cford32 string s. 578 func DecodeString(s string) ([]byte, error) { 579 buf := []byte(s) 580 l := stripNewlines(buf, buf) 581 n, err := decode(buf, buf[:l]) 582 return buf[:n], err 583 } 584 585 // stripNewlines removes newline characters and returns the number 586 // of non-newline characters copied to dst. 587 func stripNewlines(dst, src []byte) int { 588 offset := 0 589 for _, b := range src { 590 if b == '\r' || b == '\n' { 591 continue 592 } 593 dst[offset] = b 594 offset++ 595 } 596 return offset 597 } 598 599 type decoder struct { 600 err error 601 r io.Reader 602 buf [1024]byte // leftover input 603 nbuf int 604 out []byte // leftover decoded output 605 outbuf [1024 / 8 * 5]byte 606 } 607 608 // NewDecoder constructs a new base32 stream decoder. 609 func NewDecoder(r io.Reader) io.Reader { 610 return &decoder{r: &newlineFilteringReader{r}} 611 } 612 613 func readEncodedData(r io.Reader, buf []byte) (n int, err error) { 614 for n < 1 && err == nil { 615 var nn int 616 nn, err = r.Read(buf[n:]) 617 n += nn 618 } 619 return 620 } 621 622 func (d *decoder) Read(p []byte) (n int, err error) { 623 // Use leftover decoded output from last read. 624 if len(d.out) > 0 { 625 n = copy(p, d.out) 626 d.out = d.out[n:] 627 if len(d.out) == 0 { 628 return n, d.err 629 } 630 return n, nil 631 } 632 633 if d.err != nil { 634 return 0, d.err 635 } 636 637 // Read nn bytes from input, bounded [8,len(d.buf)] 638 nn := (len(p)/5 + 1) * 8 639 if nn > len(d.buf) { 640 nn = len(d.buf) 641 } 642 643 nn, d.err = readEncodedData(d.r, d.buf[d.nbuf:nn]) 644 d.nbuf += nn 645 if d.nbuf < 1 { 646 return 0, d.err 647 } 648 649 // Decode chunk into p, or d.out and then p if p is too small. 650 nr := d.nbuf 651 if d.err != io.EOF && nr%8 != 0 { 652 nr -= nr % 8 653 } 654 nw := DecodedLen(d.nbuf) 655 656 if nw > len(p) { 657 nw, err = decode(d.outbuf[0:], d.buf[0:nr]) 658 d.out = d.outbuf[0:nw] 659 n = copy(p, d.out) 660 d.out = d.out[n:] 661 } else { 662 n, err = decode(p, d.buf[0:nr]) 663 } 664 d.nbuf -= nr 665 for i := 0; i < d.nbuf; i++ { 666 d.buf[i] = d.buf[i+nr] 667 } 668 669 if err != nil && (d.err == nil || d.err == io.EOF) { 670 d.err = err 671 } 672 673 if len(d.out) > 0 { 674 // We cannot return all the decoded bytes to the caller in this 675 // invocation of Read, so we return a nil error to ensure that Read 676 // will be called again. The error stored in d.err, if any, will be 677 // returned with the last set of decoded bytes. 678 return n, nil 679 } 680 681 return n, d.err 682 } 683 684 type newlineFilteringReader struct { 685 wrapped io.Reader 686 } 687 688 func (r *newlineFilteringReader) Read(p []byte) (int, error) { 689 n, err := r.wrapped.Read(p) 690 for n > 0 { 691 s := p[0:n] 692 offset := stripNewlines(s, s) 693 if err != nil || offset > 0 { 694 return offset, err 695 } 696 // Previous buffer entirely whitespace, read again 697 n, err = r.wrapped.Read(p) 698 } 699 return n, err 700 }