diff --git a/aces.go b/aces.go index cf9e01c..14aa6c4 100644 --- a/aces.go +++ b/aces.go @@ -7,6 +7,7 @@ import ( "io" "math" "math/big" + "strings" ) // size of the buffers used by BitReader and BitWriter. @@ -40,6 +41,7 @@ func NewBitReader(chunkLen uint8, in io.Reader) (*BitReader, error) { // NewBitReaderSize is like NewBitReader but allows setting the internal buffer size func NewBitReaderSize(chunkLen uint8, in io.Reader, bufSize int) (*BitReader, error) { + fmt.Println("bufSize", bufSize) // bufSize % chunkLen == 0 so that we never have to read across the buffer boundary br := &BitReader{chunkLen: chunkLen, in: in, bufSize: bufSize - bufSize%int(chunkLen)} br.buf = make([]byte, br.bufSize) @@ -178,19 +180,31 @@ type Coding interface { // This is because most encoders interpret data as a number and use a base conversion algorithm to convert it to the // character set. For non-power-of-2 charsets, this requires all data to be read before encoding, which is not possible // with streams. To enable stream encoding for non-power-of-2 charsets, Aces converts a default of 4 bytes (adjustable -// with Coding.SetByteChunkSize) of data at a time, which is not the same as converting the base of the entire data. +// with Coding.SetByteChunkSize) of data at a time, which is not the same as converting the base of the entire data. If +// stream encoding is not necessary, use StaticCoding, for which using the base58 character set, for example, will +// produce the same output as a base58-specific encoder. func NewCoding(charset []rune) (Coding, error) { + if err := checkSet(charset); err != nil { + return nil, err + } + if len(charset)&(len(charset)-1) == 0 && len(charset) < 256 { // is power of 2? + return newTwoCoding(charset) + } + return newAnyCoding(charset) +} + +func checkSet(charset []rune) error { + if len(charset) <= 2 { + return errors.New("charset length must be greater than 2") + } seen := make(map[rune]bool) for _, r := range charset { if seen[r] { - return nil, errors.New("charset contains duplicates: '" + string(r) + "'") + return errors.New("charset contains duplicates: '" + string(r) + "'") } seen[r] = true } - if len(charset)&(len(charset)-1) == 0 && len(charset) < 256 { // is power of 2? - return newTwoCoding(charset) - } - return newAnyCoding(charset) + return nil } // twoCoding is for character sets of a length that is a power of 2. @@ -209,7 +223,7 @@ func newTwoCoding(charset []rune) (*twoCoding, error) { "\n want: a power of 2 (nearest is", 1<