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  }