base64

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 15, 2025 License: BSD-3-Clause Imports: 6 Imported by: 0

README

Fast base64 encoder/decoder

This base64 encoder/decoder is faster than stdlib base64 package.

Encoding is 70% faster on ARM64 (Mac book M2) and 36% on AMD64 (i5 11th Gen).

Decoding MIME encoded base64, which is base64 with a newline every 76 character, is 32% faster on ARM64 and 5% faster on AMD64.

Decoding pure base64 without padding and characters to ignore is 7% faster on ARM64 and 32% faster on AMD64.

Testing and benchmarking

Testing covers 100% of the code.

A CLI program is provided to generate benchmarks of the three typical usages.

API

Usage is similar to the standard library. The predefined StdEncoding and RawStandard encoding is for base64 using the standard alphabet. The former is with padding, and the later without padding. Decoding is strict by default for security reason. The decoding methods will ignore \n and \r characters.

The URLEncoding and RawURLEncoding are using the URL compatible alphabet defined in RFC4648. The former is for padded base64 encoding, and the later without. Decoding is strict by default. The decoding methods will ignore \n and \r characters.

The function NewEncoding(alphabet, ignore, padding, bitPadding) allows to define an encoding with a user defined alphabet, any set of ASCII characters to ignore, a user defined padding character or none, and Strict or Lax bit padding checking which doesn't require the padding bits to be 0.

Two alphabets are predefined, StdAlphabet and URLAlphabet. The characters to ignore may be nil, IgnoreNone, IgnoreNewlineOnly, IgnoreAll. The user may provide a custom ignore map which is a slice of 256 bytes with the values Invalid or Ignore. The function MakeIgnore is a handy function to create such ignore map.

The padding argument is a rune whose value is used as padding character unless it has the value NoPadding.

The bitPadding argument may be Strict to enforce 0 bit padding check, or Lax to not check the padding bits.

Final word

There is room for enhancement by using SIMD instructions. We didn't explore this option.

Documentation

Index

Constants

View Source
const (
	NoPadding  rune       = -1     // No padding characters are appended.
	StdPadding rune       = '='    // Appends the padding character '='.
	Strict     BitPadding = false  // Requires zero padding bits.
	Lax        BitPadding = true   // Ignores padding bits.
	Ignore     byte       = 1 << 6 // Code of character to ignore.
	Invalid    byte       = 2 << 6 // Code of invalid character.

)
View Source
const StdAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

StdAlphabet is the standard base64 alphabet (see RFC4648).

View Source
const URLAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"

URLAlphabet is an url compatible alphabet (see RFC4648).

Variables

View Source
var (
	// Only the alphabet and the padding characters are valid.
	IgnoreNone = MakeIgnore(Invalid)

	// Only the alphabet and the padding characters are valid,
	// and the \n and \r characters are skipped.
	IgnoreNewlinesOnly = MakeIgnore(Invalid, '\n', '\r')

	// All characters not in the alphabet are ignored and skipped.
	IgnoreAll = MakeIgnore(Ignore)
)
View Source
var (
	// StdEncoding uses the standard base64 alphabet, skips
	// newlines, and appends = padding.
	StdEncoding = MustNewEncoding(StdAlphabet, IgnoreNewlinesOnly, StdPadding, Strict)

	// RawStdEncoding uses the standard base64 alphabet,
	// skips newlines, and doesn’t append padding.
	RawStdEncoding = MustNewEncoding(StdAlphabet, IgnoreNewlinesOnly, NoPadding, Strict)

	// URLEncoding uses the URL compatible base64 alphabet,
	// skips newlines, and appends = padding.
	URLEncoding = MustNewEncoding(URLAlphabet, IgnoreNewlinesOnly, StdPadding, Strict)

	// RawURLEncoding uses the URL compatible base64 alphabet,
	// skips newlines, and doesn’t append padding.
	RawURLEncoding = MustNewEncoding(URLAlphabet, IgnoreNewlinesOnly, NoPadding, Strict)
)
View Source
var ErrBadBitPadding = fmt.Errorf("%w: bad bit padding", ErrInvalid)
View Source
var ErrBadCharacter = fmt.Errorf("%w: bad character", ErrInvalid)
View Source
var ErrBadLength = fmt.Errorf("%w: bad length", ErrInvalid)
View Source
var ErrBadPadding = fmt.Errorf("%w: bad padding", ErrInvalid)

Functions

func MakeIgnore

func MakeIgnore(b byte, inverse ...byte) []byte

MakeIgnore constructs an ignoring rule map. All the map is set to value b (Invalid or Ignore), o lists the indexes with the opposite value.

Types

type BitPadding

type BitPadding bool

type Encoding

type Encoding struct {
	// contains filtered or unexported fields
}

An Encoding is a radix 64 encoding/decoding scheme, defined by a 64-character alphabet. The most common encoding is the "base64" encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM (RFC 1421). RFC 4648 also defines an alternate encoding, which is the standard encoding with - and _ substituted for + and /.

func MustNewEncoding

func MustNewEncoding(alphabet string, ignore []byte, padding rune, bitPadding BitPadding) *Encoding

MustNewEncoding is like NewEncoding, but it panics in case of error.

func NewEncoding

func NewEncoding(alphabet string, ignore []byte, padding rune, bitPadding BitPadding) (*Encoding, error)

NewEncoding returns a new base64 encoding using the given 64 letter alphabet. The decoding rule tells which byte should be ignored of considered invalid. Use MakeDecodingRule to create a decoding rule. The padding defines the padding character. It may be StdPadding ('='), NoPadding, or a user specified padding character whose value must be smaller than 128. The bitPadding checking rule is Strict or Lax. When strict, it is an error when the padding bits are not zero. When lax, they are not checked. Strict should be used by default for security.

func (*Encoding) AppendDecode

func (enc *Encoding) AppendDecode(dst, src []byte) ([]byte, error)

AppendDecode appends the decoded src to dst and returns the number of bytes read. When error is not nil, the number is the offset in src to the character that caused the error.

func (*Encoding) AppendEncode

func (enc *Encoding) AppendEncode(dst []byte, src []byte) []byte

AppendEncode appends the encoding of src to dst.

func (*Encoding) Decode

func (enc *Encoding) Decode(dst, src []byte) (int, error)

Decode decodes the base64 encoded src into dst. Panics if dst is not big enough. The required size is determined with the DecodedLength method.

func (*Encoding) DecodedLen

func (enc *Encoding) DecodedLen(l int) int

DecodedLen returns the maximum resulting byte length when decoding l bytes.

func (*Encoding) Encode

func (enc *Encoding) Encode(dst []byte, src []byte) []byte

Encode encodes src into dst. Panics when dst is smaller than the size returned by EncodeLength.

func (*Encoding) EncodeToString

func (enc *Encoding) EncodeToString(src []byte) string

EncodeToString encodes src into a string.

func (*Encoding) EncodedLen

func (enc *Encoding) EncodedLen(l int) int

EncodedLen returns the resulting byte length when encoding l bytes.

type ErrDecode

type ErrDecode struct {
	// contains filtered or unexported fields
}

ErrDecode is returned by decoding methods and provide the offset of the error.

func (ErrDecode) Error

func (e ErrDecode) Error() string

Error returns the error as a string.

func (ErrDecode) Offset

func (e ErrDecode) Offset() int

Offset returns the offset of the error.

func (ErrDecode) Unwrap

func (e ErrDecode) Unwrap() error

Unwrap extracts the parent error.

type Error

type Error string

Error is a base64 error.

const ErrInvalid Error = "base64"

ErrInvalid sentinel error

func (Error) Error

func (e Error) Error() string

Error returns error as a string.

Directories

Path Synopsis
cmd
base64bench command

Jump to

Keyboard shortcuts

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