rencode

package module
v0.1.8 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2021 License: GPL-2.0 Imports: 11 Imported by: 8

README

go-rencode

GoDoc

go-rencode is a Go implementation of aresch/rencode.

The rencode logic is similar to bencode. For complex, heterogeneous data structures with many small elements, r-encodings take up significantly less space than b-encodings.

Usage

Example of encoder construction and use:

	b := bytes.Buffer{}
	e := rencode.NewEncoder(&b)
	
	err := e.Encode(100, true, "hello world", rencode.NewList(42, "nesting is awesome"), 3.14, rencode.Dictionary{})

You can use either specific methods to encode one of the supported types, or the interface-generic Encode() method.

Example of decoder construction:

	e := rencode.NewDecoder(&b)

The DecodeNext() method can be used to decode the next value from the rencode stream; however this method returns an interface{} while it is usually the norm that there is an expected type instead; in such cases, it is advised to use the Scan() method instead, which accepts a pointer to any of the supported types.

Example:

	var i int
	var b bool
	var s string
	var l rencode.List
	err := e.Scan(&i, &b, &s, &l)

You can also decode a dictionary directly into a struct:

	var s struct {
		Alpha int
		Beta  string
		Gamma float64 `rencode:"rencode-exclude"`
	}
	var d Dictionary
	d.Add("alpha", int(54123))
	d.Add("beta", "test")

	err := d.ToStruct(&s, "rencode-exclude")

In this example every field/value of the dictionary must be mapped to a struct field, except those tagged as rencode-exclude. This works as well with nested dictionaries mapping to nested structs.

Supported types

Only the following types are supported:

  • rencode.List
  • rencode.Dictionary
  • big.Int (any integer with more than 63 bits of information)
  • bool
  • float32, float64
  • []byte, string (all strings are stored as byte slices anyway)
  • int8, int16, int32, int64, int
  • uint8, uint16, uint32, uint64, uint
Accessory types

The rencode.List and rencode.Dictionary implement Python-alike features and can store values and keys of the simpler types enumerated above.

TODO

  • try using reflect.Value instead of the generated code

Credits

  • This Go version: gdm85
  • Original Python version: Petru Paler, Connelly Barnes et al.
  • Cython version: Andrew Resch

License

go-rencode is licensed under GNU GPL v2, see COPYING for license information.

Documentation

Overview

Package rencode is a Go implementation of https://github.com/aresch/rencode

The rencode logic is similar to bencode (https://en.wikipedia.org/wiki/Bencode). For complex, heterogeneous data structures with many small elements, r-encodings take up significantly less space than b-encodings.

Usage

Example of encoder construction and use:

b := bytes.Buffer{}
e := rencode.NewEncoder(&b)

err := e.Encode(100, true, "hello world", rencode.NewList(42, "nesting is awesome"), 3.14, rencode.Dictionary{})

You can use either specific methods to encode one of the supported types, or the interface-generic Encode() method.

Example of decoder construction:

e := rencode.NewDecoder(&b)

The DecodeNext() method can be used to decode the next value from the rencode stream; however this method returns an interface{} while it is usually the norm that there is an expected type instead; in such cases, it is advised to use the Scan() method instead, which accepts a pointer to any of the supported types.

Example:

var i int
var b bool
var s string
var l rencode.List
err := e.Scan(&i, &b, &s, &l)

Supported types

Only the following types are supported:

  • rencode.List
  • rencode.Dictionary
  • big.Int (any integer with more than 63 bits of information)
  • bool
  • float32, float64
  • []byte, string (all strings are stored as byte slices anyway)
  • int8, int16, int32, int64, int
  • uint8, uint16, uint32, uint64, uint

Accessory types

The rencode.List and rencode.Dictionary implement Python-alike features and can store values and keys of the simpler types enumerated above.

Index

Constants

View Source
const (
	MAX_INT_LENGTH = 64 // Maximum length of integer when written as base 10 string.
	// The bencode 'typecodes' such as i, d, etc have been extended and relocated on the base-256 character set.
	CHR_LIST    = 59
	CHR_DICT    = 60
	CHR_INT     = 61
	CHR_INT1    = 62
	CHR_INT2    = 63
	CHR_INT4    = 64
	CHR_INT8    = 65
	CHR_FLOAT32 = 66
	CHR_FLOAT64 = 44
	CHR_TRUE    = 67
	CHR_FALSE   = 68
	CHR_NONE    = 69
	CHR_TERM    = 127
	// Positive integers with value embedded in typecode.
	INT_POS_FIXED_START = 0
	INT_POS_FIXED_COUNT = 44
	// Dictionaries with length embedded in typecode.
	DICT_FIXED_START = 102
	DICT_FIXED_COUNT = 25
	// Negative integers with value embedded in typecode.
	INT_NEG_FIXED_START = 70
	INT_NEG_FIXED_COUNT = 32
	// Strings with length embedded in typecode.
	STR_FIXED_START = 128
	STR_FIXED_COUNT = 64
	// Lists with length embedded in typecode.
	LIST_FIXED_START = STR_FIXED_START + STR_FIXED_COUNT
	LIST_FIXED_COUNT = 64
)

Constants as defined in https://github.com/aresch/rencode/blob/master/rencode/rencode.pyx

Variables

View Source
var (
	// ErrKeyAlreadyExists is the error returned when the specified key is already defined within the dictionary
	ErrKeyAlreadyExists = errors.New("key already exists in dictionary")
)
View Source
var (
	// ErrKeyNotFound is the error returned when specified key does not exist in List or Dictionary
	ErrKeyNotFound = errors.New("key not found")
)

Functions

func Dump added in v0.1.1

func Dump(w io.Writer, b []byte) error

Dump will dump the content of the specified bytes slice to the specified writer, for debugging purposes.

func ToSnakeCase added in v0.1.1

func ToSnakeCase(s string) string

ToSnakeCase will convert a 'CamelCase' string to the corresponding 'snake_case' representation. Acronyms are converted to lower-case and preceded by an underscore.

Types

type ConversionOverflow

type ConversionOverflow struct {
	SourceTypeName string
	DestTypeName   string
}

ConversionOverflow is returned when the scanned integer would overflow the destination integer

func (ConversionOverflow) Error

func (co ConversionOverflow) Error() string

type Decoder

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

Decoder implements a rencode decoder

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder returns a rencode decoder that sources all bytes from the specified reader

func (*Decoder) DecodeNext

func (r *Decoder) DecodeNext() (interface{}, error)

DecodeNext returns the next available object stored in the rencode stream. If no more objects are available, an io.EOF error will be returned.

func (*Decoder) Scan

func (d *Decoder) Scan(targets ...interface{}) error

Scan will scan the decoder data to fill in the specified target objects; if possible, a conversion will be performed. If targets have not pointer types or if the conversion is not possible, an error will be returned.

type Dictionary

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

Dictionary is a rencode-specific dictionary that allows any type of key to be mapped to any type of value

func (*Dictionary) Add

func (d *Dictionary) Add(key, value interface{})

Add appends a new (key, value) pair; does not check if key already exists.

func (*Dictionary) Get added in v0.1.2

func (d *Dictionary) Get(key interface{}) (interface{}, bool)

Get returns the value in the dictionary corresponding to the specified key. If the key is not found then 'nil, false' is returned instead. Keys of type 'string' and '[]byte' are both compared as if they were strings. NOTE: slice keys cannot be used with this method.

func (*Dictionary) Keys

func (d *Dictionary) Keys() []interface{}

Keys returns all defined keys

func (*Dictionary) Length

func (d *Dictionary) Length() int

Length returns the total count of elements

func (*Dictionary) ToStruct

func (d *Dictionary) ToStruct(dest interface{}, excludeAnnotationTag string) error

ToStruct will map a Dictionary into a struct, recursively. All dictionary keys must map to a field or an error will be returned. It is possible to exclude fields with a specific annotation.

func (*Dictionary) Values

func (d *Dictionary) Values() []interface{}

Values returns all stored values

func (*Dictionary) Zip

func (d *Dictionary) Zip() (map[string]interface{}, error)

Zip returns a map with strings as keys or an error if a duplicate key exists.

type Encoder

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

Encoder implements a rencode encoder

func NewEncoder

func NewEncoder(w io.Writer) Encoder

NewEncoder returns a rencode encoder that writes on specified Writer

func (*Encoder) Encode

func (r *Encoder) Encode(values ...interface{}) error

Encode will ingest and encode multiple values of the following supported types:

  • big.Int
  • List, Dictionary
  • bool
  • float32, float64
  • []byte, string (all strings are stored as byte slices anyway)
  • int8, int16, int32, int64, int
  • uint8, uint16, uint32, uint64, uint

func (*Encoder) EncodeBigNumber

func (r *Encoder) EncodeBigNumber(s string) error

EncodeBigNumber encodes a big number (> 2^64)

func (*Encoder) EncodeBool

func (r *Encoder) EncodeBool(b bool) error

EncodeBool encodes a bool value

func (*Encoder) EncodeBytes

func (r *Encoder) EncodeBytes(b []byte) error

EncodeBytes encodes a byte slice; all strings should be encoded as byte slices

func (*Encoder) EncodeFloat32

func (r *Encoder) EncodeFloat32(f float32) error

EncodeFloat32 encodes a float32 value

func (*Encoder) EncodeFloat64

func (r *Encoder) EncodeFloat64(f float64) error

EncodeFloat64 encodes an float64 value

func (*Encoder) EncodeInt16

func (r *Encoder) EncodeInt16(x int16) error

EncodeInt16 encodes an int16 value

func (*Encoder) EncodeInt32

func (r *Encoder) EncodeInt32(x int32) error

EncodeInt32 encodes an int32 value

func (*Encoder) EncodeInt64

func (r *Encoder) EncodeInt64(x int64) error

EncodeInt64 encodes an int64 value

func (*Encoder) EncodeInt8

func (r *Encoder) EncodeInt8(x int8) error

EncodeInt8 encodes an int8 value

func (*Encoder) EncodeNone

func (r *Encoder) EncodeNone() error

EncodeNone encodes a nil value without any type information

type List

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

List is a rencode-specific list that allows any type of value to be concatenated

func NewList

func NewList(values ...interface{}) List

NewList returns a new list with the values specified as arguments

func (*List) Add

func (l *List) Add(values ...interface{})

Add appends one or more values to the list

func (*List) Length

func (l *List) Length() int

Length returns the total count of elements

func (*List) Scan

func (l *List) Scan(targets ...interface{}) error

Scan will scan the list to fill in the specified target objects; if possible, a conversion will be performed. If targets have not pointer types or if the conversion is not possible, an error will be returned. 32-bit integers larger than 16777216 will be imprecisely allowed to cast to float32.

func (*List) Shift added in v0.1.5

func (l *List) Shift(n int) int

Shift will remove the specified number of elements from the front of the List and return how many were removed. This will be different than n if the List is shorter.

func (*List) Values

func (l *List) Values() []interface{}

Values returns all values in the list

Jump to

Keyboard shortcuts

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