sexprs

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 18, 2018 License: MIT Imports: 9 Imported by: 2

README

GoDoc

Symbolic expressions (S-expressions) for Go

sexprs implements canonical S-expressions.

Installation

go get github.com/eadmund/sexprs

See the godoc for more documentation & examples.

Documentation

Overview

Package sexprs implements Ron Rivest's canonical S-expressions (c.f. http://people.csail.mit.edu/rivest/Sexp.txt or rivest-draft.txt in this package) in Go. I'm indebted to Inferno's sexprs(2), whose API I first accidentally, and then deliberately, mimicked. I've copied much of its style, only making it more Go-like.

Canonical S-expressions are a compact, easy-to-parse, ordered, hashable data representation ideal for cryptographic operations. They are simpler and more compact than either JSON or XML.

An S-expression is composed of lists and atoms. An atom is a string of bytes, with an optional display hint, also a byte string. A list can contain zero or more atoms or lists.

There are two representations of an S-expression: the canonical representation is a byte-oriented, packed representation, while the advanced representation is string-oriented and more traditional in appearance.

The S-expression ("foo" "bar" ["bin"]"baz quux") is canonically:

(3:foo3:bar[3:bin]8:quux)

Among the valid advanced representations are:

(foo 3:bar [bin]"baz quux")

and:

("foo" #626172# [3:bin]|YmF6IHF1dXg=|)

There is also a transport encoding (intended for use in 7-bit transport modes), delimited with {}:

{KDM6Zm9vMzpiYXJbMzpiaW5dODpiYXogcXV1eCk=}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsList

func IsList(s Sexp) bool

Types

type Atom

type Atom struct {
	DisplayHint []byte
	Value       []byte
}

An Atom is a byte sequence, together with an optional display hint, also a byte sequence. The display hint could potentially be used to inform a user agent that a value should be interpreted as, e.g., a JPEG. One might use MIME types as display hints, e.g. text/plain"This is plain text" (although this particular case is somewhat unlikely, since most user agents are likely to default to plain text). Note that there are no semantics attached to the value; it could be a UTF-8 string, a little-endian integer, a big-endian integer or any other byte sequence.

func (Atom) Base64String

func (a Atom) Base64String() (s string)

func (Atom) Equal

func (a Atom) Equal(b Sexp) bool

func (Atom) Pack

func (a Atom) Pack() []byte

Pack returns the canonical form of an Atom: a decimal indicating its length in bytes, a colon, and then the bytes. If there is a display hint, it is prepended within square brackets. E.g. "foo" is packed as "3:foo" and "bar" with a display hint of "text/plain" is packed as "[10:text/plain]3:bar".

Example
foo := Atom{Value: []byte("foo")}
fmt.Println(string(foo.Pack()))
bar := Atom{DisplayHint: []byte("text/plain"), Value: []byte("bar")}
fmt.Println(string(bar.Pack()))
Output:

3:foo
[10:text/plain]3:bar

func (Atom) PackedLen

func (a Atom) PackedLen() (size int)

func (Atom) String

func (a Atom) String() string
Example
foo := Atom{Value: []byte("foo")}
fmt.Println(foo.String())
foo.Value = []byte("bar baz")
fmt.Println(foo.String())
foo.Value = []byte("bar\nbaz")
fmt.Println(foo.String())
foo.Value = []byte{0, 1, 2, 3}
fmt.Println(foo.String())
Output:

foo
"bar baz"
"bar\nbaz"
|AAECAw==|

type List

type List []Sexp

A List is a slice of Lists and Atoms.

func (List) Base64String

func (l List) Base64String() string

func (List) Equal

func (a List) Equal(b Sexp) bool

func (List) Pack

func (l List) Pack() []byte

Pack returns each component of List l within parentheses, e.g. "(foo)" would pack as "(3:foo)".

Example
list := List{Atom{Value: []byte("foo")}, List{Atom{Value: []byte("bar baz"), DisplayHint: []byte("text/plain")}, Atom{DisplayHint: []byte{'\n'}}}}
fmt.Println(string(list.Pack()))
readList, _, err := Parse([]byte(list.String()))
if err != nil {
	panic(err)
}
fmt.Println(readList.Equal(list))
Output:

(3:foo([10:text/plain]7:bar baz[1:
]0:))
true

func (List) PackedLen

func (l List) PackedLen() (size int)

func (List) String

func (l List) String() string
Example
list := List{Atom{Value: []byte("foo")}, List{Atom{Value: []byte("bar baz"), DisplayHint: []byte("text/plain")}, Atom{DisplayHint: []byte{1, 2, 3}}}}
fmt.Println(list.String())
readList, _, err := Parse([]byte(list.String()))
if err != nil {
	panic(err)
}
fmt.Println(readList.Equal(list))
Output:

(foo ([text/plain]"bar baz" [|AQID|]""))
true

type Sexp

type Sexp interface {
	// String returns an advanced representation of the object, with
	// no line breaks.
	String() string

	// Base64String returns a transport-encoded rendering of the
	// S-expression
	Base64String() string

	// Pack returns the canonical representation of the object.  It
	// will always return the same sequence of bytes for the same
	// object.
	Pack() []byte

	// PackedLen returns the size in bytes of the canonical
	// representation.
	PackedLen() int

	// Equal will return true if its receiver and argument are
	// identical.
	Equal(b Sexp) bool
	// contains filtered or unexported methods
}

Sexp is the interface implemented by both lists and atoms.

func Parse

func Parse(s []byte) (sexpr Sexp, rest []byte, err error)

Parse returns the first S-expression in byte string s, the unparsed rest of s and any error encountered

func Read

func Read(r *bufio.Reader) (s Sexp, err error)

Read a single S-expression from buffered IO r, returning any error encountered. May return io.EOF if at end of r; may return a valid S-expression and io.EOF if the EOF was encountered at the end of parsing.

Jump to

Keyboard shortcuts

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