memcached

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package memcached provides a codec for decoding PHP memcached cache entries in Go.

PHP's memcached PECL extension stores each cache value alongside a 32-bit flags field that encodes the serializer type and compression algorithm used. This package abstracts the two-stage pipeline (decompress then deserialize) behind pluggable interfaces, with built-in support for igbinary, JSON, FastLZ, and Zlib.

Quick Start

codec := memcached.NewCodec()
val, err := codec.Decode(item.Value, item.Flags)

Index

Constants

View Source
const (
	FlagString     uint32 = 0 // Raw string
	FlagLong       uint32 = 1 // Integer
	FlagDouble     uint32 = 2 // Float
	FlagBool       uint32 = 3 // Boolean
	FlagSerialized uint32 = 4 // PHP serialize()
	FlagIgbinary   uint32 = 5 // igbinary
	FlagJSON       uint32 = 6 // JSON
	FlagMsgpack    uint32 = 7 // Msgpack
)

Serializer type flags (lower 4 bits of the flags field).

View Source
const (
	FlagCompressed uint32 = 1 << 4 // Data is compressed (16)
	FlagZlib       uint32 = 1 << 5 // zlib compression (32)
	FlagFastlz     uint32 = 1 << 6 // FastLZ compression (64)
	FlagZstd       uint32 = 1 << 7 // Zstandard compression (128)
)

Compression flags (bit flags in the upper nibble of the low byte).

View Source
const (
	SerializerMask  uint32 = 0x0F // Lower 4 bits: serializer type
	CompressionMask uint32 = FlagZlib | FlagFastlz | FlagZstd
)

Masks for extracting parts of the flags.

Variables

This section is empty.

Functions

func CompressionName

func CompressionName(flags uint32) string

CompressionName returns a human-readable name for the compression type.

func ExplainFlags

func ExplainFlags(flags uint32) string

ExplainFlags returns a human-readable explanation of cache flags.

func HasIgbinaryHeader added in v0.3.1

func HasIgbinaryHeader(data []byte) bool

HasIgbinaryHeader returns true when data starts with a valid igbinary header.

func IsCompressed

func IsCompressed(flags uint32) bool

IsCompressed returns true if the compressed flag is set.

func IsIgbinaryFlags added in v0.3.1

func IsIgbinaryFlags(flags uint32) bool

IsIgbinaryFlags returns true when flags select the igbinary serializer.

func SerializerName

func SerializerName(flags uint32) string

SerializerName returns a human-readable name for the serializer type.

func SerializerType

func SerializerType(flags uint32) uint32

SerializerType extracts the serializer type from cache flags.

func ShouldTryIgbinary added in v0.3.1

func ShouldTryIgbinary(flags uint32, data []byte) bool

ShouldTryIgbinary returns true when either flags or payload indicate igbinary.

Types

type BoolSerializer

type BoolSerializer struct{}

BoolSerializer deserializes boolean values stored by PHP's memcached extension.

PHP stores true as "1" and false as "" (empty bytes) with flags type = FlagBool.

func (*BoolSerializer) Deserialize

func (s *BoolSerializer) Deserialize(data []byte) (any, error)

Deserialize parses a PHP boolean value into a Go bool.

type Codec

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

Codec decodes raw cache values by orchestrating decompression and deserialization using pluggable Compressor and Serializer implementations.

It reads a flags field to determine which compression and serialization algorithms to use, then dispatches to the registered implementations.

Create one with NewCodec for standard PHP memcached defaults, or use NewCodecBuilder for custom configurations.

func NewCodec

func NewCodec() *Codec

NewCodec creates a Codec pre-configured with standard PHP memcached defaults: FastLZ + Zlib compressors, and Igbinary + String + JSON serializers.

This is a convenience constructor. Use NewCodecBuilder to customize.

func (*Codec) Decode

func (c *Codec) Decode(data []byte, flags uint32) (any, error)

Decode decodes a raw cache value using flags to determine the compression and serialization format.

Pipeline:

  1. If IsCompressed(flags), decompress using the matching Compressor.
  2. Deserialize using the matching Serializer for SerializerType(flags).

type CodecBuilder

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

CodecBuilder provides a fluent API for constructing a Codec with custom compressor and serializer implementations.

Example:

codec := memcached.NewCodecBuilder().
    WithCompressor(memcached.FlagFastlz, &memcached.FastlzCompressor{}).
    WithCompressor(memcached.FlagZstd, &myZstdCompressor{}).
    WithSerializer(memcached.FlagJSON, &memcached.JSONSerializer{}).
    WithSerializer(memcached.FlagIgbinary, &memcached.IgbinarySerializer{}).
    WithFallbackCompressor(&memcached.FastlzCompressor{}).
    Build()

func NewCodecBuilder

func NewCodecBuilder() *CodecBuilder

NewCodecBuilder creates a new empty builder.

func (*CodecBuilder) Build

func (b *CodecBuilder) Build() *Codec

Build creates the Codec from the builder configuration.

func (*CodecBuilder) WithCompressor

func (b *CodecBuilder) WithCompressor(flag uint32, c Compressor) *CodecBuilder

WithCompressor registers a compressor for a specific compression flag bit. The flag should be a single bit flag like FlagFastlz, FlagZlib, or FlagZstd.

func (*CodecBuilder) WithFallbackCompressor

func (b *CodecBuilder) WithFallbackCompressor(c Compressor) *CodecBuilder

WithFallbackCompressor sets the compressor used when the compressed flag is set but no specific compression algorithm flag matches.

func (*CodecBuilder) WithFallbackSerializer

func (b *CodecBuilder) WithFallbackSerializer(s Serializer) *CodecBuilder

WithFallbackSerializer sets the serializer used when the type flag doesn't match any registered serializer.

func (*CodecBuilder) WithSerializer

func (b *CodecBuilder) WithSerializer(flag uint32, s Serializer) *CodecBuilder

WithSerializer registers a serializer for a specific serializer type value. The flag should be a type constant like FlagIgbinary, FlagJSON, or FlagString.

type Compressor

type Compressor interface {
	// Decompress decompresses data and returns the original bytes.
	Decompress(data []byte) ([]byte, error)
}

Compressor handles decompression of cache values.

Implement this interface to add support for custom compression algorithms (e.g., zstd, lz4, snappy).

type DoubleSerializer

type DoubleSerializer struct{}

DoubleSerializer deserializes float values stored as their string representation.

PHP's memcached extension stores floats this way when the value is a scalar (flags type = FlagDouble). For example, 3.14 is stored as the bytes "3.14".

func (*DoubleSerializer) Deserialize

func (s *DoubleSerializer) Deserialize(data []byte) (any, error)

Deserialize parses a string-encoded float into float64.

type FastlzCompressor

type FastlzCompressor struct{}

FastlzCompressor decompresses data using the FastLZ algorithm.

This is the default compressor used by PHP's memcached extension.

func (*FastlzCompressor) Decompress

func (c *FastlzCompressor) Decompress(data []byte) ([]byte, error)

Decompress decompresses FastLZ-compressed data. Expects the go-fastlz framing format (4-byte uncompressed length prefix).

type IgbinarySerializer

type IgbinarySerializer struct{}

IgbinarySerializer deserializes igbinary-encoded data using the github.com/RezaKargar/go-igbinary package.

func (*IgbinarySerializer) Deserialize

func (s *IgbinarySerializer) Deserialize(data []byte) (any, error)

Deserialize decodes igbinary data into native Go types.

type JSONSerializer

type JSONSerializer struct{}

JSONSerializer deserializes JSON-encoded data into native Go types.

func (*JSONSerializer) Deserialize

func (s *JSONSerializer) Deserialize(data []byte) (any, error)

Deserialize decodes JSON data into Go values (map, slice, string, number, bool, nil).

type LongSerializer

type LongSerializer struct{}

LongSerializer deserializes integer values stored as their string representation.

PHP's memcached extension stores integers this way when the value is a scalar (flags type = FlagLong). For example, the integer 42 is stored as the bytes "42".

func (*LongSerializer) Deserialize

func (s *LongSerializer) Deserialize(data []byte) (any, error)

Deserialize parses a string-encoded integer into int64.

type Serializer

type Serializer interface {
	// Deserialize converts raw bytes into a Go value.
	Deserialize(data []byte) (any, error)
}

Serializer handles deserialization of cache values.

Implement this interface to add support for custom serialization formats (e.g., msgpack, protobuf, php serialize).

type StringSerializer

type StringSerializer struct{}

StringSerializer returns the raw bytes as a Go string (no transformation).

func (*StringSerializer) Deserialize

func (s *StringSerializer) Deserialize(data []byte) (any, error)

Deserialize returns the data as a string.

type ZlibCompressor

type ZlibCompressor struct {
	// LengthPrefixed indicates whether the data has a 4-byte little-endian
	// uncompressed length prefix before the zlib stream. Defaults to true,
	// matching the PHP memcached extension format.
	LengthPrefixed bool
}

ZlibCompressor decompresses data using the zlib algorithm.

func NewZlibCompressor

func NewZlibCompressor(lengthPrefixed bool) *ZlibCompressor

NewZlibCompressor creates a ZlibCompressor. If lengthPrefixed is true, expects 4-byte LE uncompressed length + zlib stream.

func (*ZlibCompressor) Decompress

func (c *ZlibCompressor) Decompress(data []byte) ([]byte, error)

Decompress decompresses zlib-compressed data.

Jump to

Keyboard shortcuts

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