cford32

package module
v1.0.1-0...-67746ef Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 21, 2024 License: BSD-3-Clause Imports: 3 Imported by: 0

README

cford32 Go Reference go test

Package cford32 implements a base32-like encoding/decoding package, with the encoding scheme specified by Douglas Crockford.

From the website, the requirements of said encoding scheme are to:

  • Be human readable and machine readable.
  • Be compact. Humans have difficulty in manipulating long strings of arbitrary symbols.
  • Be error resistant. Entering the symbols must not require keyboarding gymnastics.
  • Be pronounceable. Humans should be able to accurately transmit the symbols to other humans using a telephone.

This is slightly different from a simple difference in encoding table from the Go's stdlib encoding/base32, as when decoding the characters i I l L are parsed as 1, and o O is parsed as 0.

This package additionally provides ways to encode uint64's efficiently, as well as efficient encoding to a lowercase variation of the encoding. The encodings never use paddings.

Why?

The main purpose I envision for this package is to create small, friendly, case-insensitive IDs. The encoding and decoding functions exist to match the API of similar packages like the standard library base32, and as such supporting adapting the code of this package for other use cases.

Examples

package main

import (
	"fmt"
	"math/rand"

	"github.com/thehowl/cford32"
)

func main() {
	gen := rand.New(rand.NewSource(12345))

	for i := 0; i < 6; i++ {
		// 1 << 35 allows us to show diverse set of compact/extended
		n := uint64(gen.Int63n(1 << 35))
		fmt.Printf("%11d: %s\n", n, string(cford32.PutCompact(n)))
	}

	// Output:
	// 14334683418: db6kt8t
	// 34093059390: g00000zr1nk9y
	//   417819965: 0ceev9x
	// 17538543416: g00000gap1vsr
	//  5407252823: 514r8aq
	// 16008560262: ex2yfm6
}

Documentation

Overview

Package cford32 implements a base32-like encoding/decoding package, with the encoding scheme specified by Douglas Crockford.

From the website, the requirements of said encoding scheme are to:

  • Be human readable and machine readable.
  • Be compact. Humans have difficulty in manipulating long strings of arbitrary symbols.
  • Be error resistant. Entering the symbols must not require keyboarding gymnastics.
  • Be pronounceable. Humans should be able to accurately transmit the symbols to other humans using a telephone.

This is slightly different from a simple difference in encoding table from the Go's stdlib `encoding/base32`, as when decoding the characters i I l L are parsed as 1, and o O is parsed as 0.

This package additionally provides ways to encode uint64's efficiently, as well as efficient encoding to a lowercase variation of the encoding. The encodings never use paddings.

Uint64 Encoding

Aside from lower/uppercase encoding, there is a compact encoding, allowing to encode all values in [0,2^34), and the full encoding, allowing all values in [0,2^64). The compact encoding uses 7 characters, and the full encoding uses 13 characters. Both are parsed unambiguously by the Uint64 decoder.

The compact encodings have the first character between ['0','f'], while the full encoding's first character ranges between ['g','z']. Practically, in your usage of the package, you should consider which one to use and stick with it, while considering that the compact encoding, once it reaches 2^34, automatically switches to the full encoding. The properties of the generated strings are still maintained: for instance, any two encoded uint64s x,y consistently generated with the compact encoding, if the numeric value is x < y, will also be x < y in lexicographical ordering. However, values [0,2^34) have a "double encoding", which if mixed together lose the lexicographical ordering property.

The Uint64 encoding is most useful for generating string versions of Uint64 IDs. Practically, it allows you to retain sleek and compact IDs for your applcation for the first 2^34 (>17 billion) entities, while seamlessly rolling over to the full encoding should you exceed that. You are encouraged to use it unless you have a requirement or preferences for IDs consistently being always the same size.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendCompact

func AppendCompact(id uint64, b []byte) []byte

AppendCompact works like PutCompact but appends to the given byte slice instead of allocating one anew.

func AppendDecode

func AppendDecode(dst, src []byte) ([]byte, error)

AppendDecode appends the cford32 decoded src to dst and returns the extended buffer. If the input is malformed, it returns the partially decoded src and an error.

func AppendEncode

func AppendEncode(dst, src []byte) []byte

AppendEncode appends the cford32 encoded src to dst and returns the extended buffer.

func AppendEncodeLower

func AppendEncodeLower(dst, src []byte) []byte

AppendEncodeLower appends the lowercase cford32 encoded src to dst and returns the extended buffer.

func Decode

func Decode(dst, src []byte) (n int, err error)

Decode decodes src using cford32. It writes at most DecodedLen(len(src)) bytes to dst and returns the number of bytes written. If src contains invalid cford32 data, it will return the number of bytes successfully written and CorruptInputError. Newline characters (\r and \n) are ignored.

func DecodeString

func DecodeString(s string) ([]byte, error)

DecodeString returns the bytes represented by the cford32 string s.

func DecodedLen

func DecodedLen(n int) int

DecodedLen returns the number of decoded bytes from n of encoded bytes when using Decode.

func Encode

func Encode(dst, src []byte)

Encode encodes src using the encoding enc, writing EncodedLen(len(src)) bytes to dst.

The encoding does not contain any padding, unlike Go's base32.

func EncodeLower

func EncodeLower(dst, src []byte)

EncodeLower is like Encode, but uses the lowercase variation of the encoding.

func EncodeToString

func EncodeToString(src []byte) string

EncodeToString returns the cford32 encoding of src.

func EncodeToStringLower

func EncodeToStringLower(src []byte) string

EncodeToStringLower returns the cford32 lowercase encoding of src.

func EncodedLen

func EncodedLen(n int) int

EncodedLen returns the number of ecnoded bytes from n of encoded bytes when using Encode.

func NewDecoder

func NewDecoder(r io.Reader) io.Reader

NewDecoder constructs a new base32 stream decoder.

func NewEncoder

func NewEncoder(w io.Writer) io.WriteCloser

NewEncoder returns a new cford32 stream encoder. Data written to the returned writer will be encoded using enc and then written to w. Base32 encodings operate in 5-byte blocks; when finished writing, the caller must Close the returned encoder to flush any partially written blocks.

func NewEncoderLower

func NewEncoderLower(w io.Writer) io.WriteCloser

NewEncoderLower is like NewEncoder, but it uses the lowercase vairation of the encoding.

func PutCompact

func PutCompact(id uint64) []byte

PutCompact returns a cford32-encoded byte slice, using the compact representation of cford32 described in the package documentation where possible (all values of id < 1<<34). The lowercase encoding is used.

The resulting byte slice will be 7 bytes long for all values that use the compact encoding, and 13 bytes long for all others.

Example
package main

import (
	"fmt"
	"math/rand"

	"github.com/thehowl/cford32"
)

func main() {
	gen := rand.New(rand.NewSource(12345))

	for i := 0; i < 6; i++ {
		// 1 << 35 allows us to show diverse set of compact/extended
		n := uint64(gen.Int63n(1 << 35))
		fmt.Printf("%11d: %s\n", n, string(cford32.PutCompact(n)))
	}
}
Output:

14334683418: db6kt8t
34093059390: g00000zr1nk9y
  417819965: 0ceev9x
17538543416: g00000gap1vsr
 5407252823: 514r8aq
16008560262: ex2yfm6

func PutUint64

func PutUint64(id uint64) [13]byte

PutUint64 returns a cford32-encoded byte array.

func PutUint64Lower

func PutUint64Lower(id uint64) [13]byte

PutUint64Lower returns a cford32-encoded byte array, swapping uppercase letters with lowercase.

For more information on how the value is encoded, see Uint64.

func Uint64

func Uint64(b []byte) (uint64, error)

Uint64 parses a cford32-encoded byte slice into a uint64.

  • The parser requires all provided character to be valid cford32 characters.
  • The parser disregards case.
  • If the first character is '0' <= c <= 'f', then the passed value is assumed encoded in the compact encoding, and must be 7 characters long.
  • If the first character is 'g' <= c <= 'z', then the passed value is assumed encoded in the full encoding, and must be 13 characters long.

If any of these requirements fail, a CorruptInputError will be returned.

Example
package main

import (
	"fmt"

	"github.com/thehowl/cford32"
)

func main() {
	val, _ := cford32.Uint64([]byte("ex2yfm6"))
	fmt.Println(val)
}
Output:

16008560262

Types

type CorruptInputError

type CorruptInputError int64

CorruptInputError is returned by parsing functions when an invalid character in the input is found. The integer value represents the byte index where the error occurred.

This is typically because the given character does not exist in the encoding.

func (CorruptInputError) Error

func (e CorruptInputError) Error() string

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL