ebml

package module
v0.0.0-...-aee7f5d Latest Latest
Warning

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

Go to latest
Published: Sep 18, 2013 License: GPL-3.0 Imports: 7 Imported by: 1

README

Go-EBML

A marshaler/unmarshaler for EBML.

It's quite simple to use:


func ExampleMarshal() {
	DoDad := new(struct {
		EbmlId      ebml.Id `ebml:"3f0000"`
		DoHickey    uint    `ebml:"4242"`
		ThingaMabob string  `ebml:"4243"`
		HumDinger   int     `ebml:"4244"`
	})

	DoDad.DoHickey = 70000
	DoDad.ThingaMabob = "huzah"
	DoDad.HumDinger = -92387

	b, _ := ebml.Marshal(*DoDad)
	fmt.Printf("0x%x\n", b)

	// Output:
	// 0x3f00009442428301117042438568757a6168424483fe971d
}

func ExampleUnmarshal() {
	data := []byte{
		0x3f, 0x00, 0x00, 0x94,
		0x42, 0x42, 0x83, 0x01, 0x11, 0x70,
		0x42, 0x43, 0x85, 0x68, 0x75, 0x7a, 0x61, 0x68,
		0x42, 0x44, 0x83, 0xfe, 0x97, 0x1d,
	}

	DoDad := new(struct {
		EbmlId      ebml.Id `ebml:"3f0000"`
		DoHickey    uint    `ebml:"4242"`
		ThingaMabob string  `ebml:"4243"`
		HumDinger   int     `ebml:"4244"`
	})

	ebml.Unmarshal(data, DoDad)
	fmt.Printf("%v\n", DoDad)
	// Output:
	// &{0 70000 huzah -92387}
}

Caveats

If an EBML DTD specifies a value as an unsigned integer, you must use a uint type. For example: the uint32 8388608 and int -8388608 may encode to identical 0x800000 24 bit arrays in an EBML stream.

EBML does not have a boolean type, but booleans are commonly defined in DTDs as zero or non-zero usigned integers.

Not Implemented

  • Floating point values.

  • Default values.

Every non-container MAY be assigned a default value. If so, its value will be added to the interpretation of the EBML data if no element with another value exists in the data.

As an example, consider this EBML DTD:

Weight := 4101 { WeightValue := 41a1 uint; WeightUnit := 41a2 string [ def:"kilogram" ]; }

If the Weight element only contains the WeightValue element, the WeightUnit element with value "kilogram" will be added when the information is semantically processed. A WeightUnit element with another value would of course override the default.

The default value can also be a symbol referring back to a previously seen symbol. If however no such symbol has been seen, i.e. it has not been encoded into the EBML data and has no default value, the element will not be added as a child on the semantic level.

Weight := 4101 { WeightValue := 41a1 uint; WeightUnit := 41a2 string [ def:WeightUnit ]; }

Documentation

Overview

Package ebml marshals and unmarshals Go structs to and from the Exensible Binary Markup Langauge.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Marshal

func Marshal(element interface{}) ([]byte, error)

Marshal returns an EBML representation of element.

Marshal first determines the Id of element from the field named 'EbmlId', then recursively traverses element. Any exported struct field of element with an `ebml` tag will be including in marshalling, with the exception of fields tagged with `ebml:"-"`.

The ebml tag should contain a valid EBML id, see the EBML documention for what constitutes a valid id.

Example
DoDad := new(struct {
	EbmlId      ebml.Id `ebml:"3f0000"`
	DoHickey    uint    `ebml:"4242"`
	ThingaMabob string  `ebml:"4243"`
	HumDinger   int     `ebml:"4244"`
})

DoDad.DoHickey = 70000
DoDad.ThingaMabob = "huzah"
DoDad.HumDinger = -92387

b, err := ebml.Marshal(*DoDad)
if err != nil {
	fmt.Println(err)
}
fmt.Printf("0x%x\n", b)
Output:

0x3f00009442428301117042438568757a6168424483fe971d

func Unmarshal

func Unmarshal(data []byte, element interface{}) error

Unmarshal unmarshals EBML data into element.

Unmarshal first determines the Id of element from the field named 'EbmlId', then recursively traverses element. Any exported struct field of element with an `ebml` tag will be including in unmarshalling, with the exception of fields tagged with `ebml:"-"`.

The ebml tag should contain a valid EBML id, see the EBML documention for what constitutes a valid id.

Example
data := []byte{
	0x3f, 0x00, 0x00, 0x94,
	0x42, 0x42, 0x83, 0x01, 0x11, 0x70,
	0x42, 0x43, 0x85, 0x68, 0x75, 0x7a, 0x61, 0x68,
	0x42, 0x44, 0x83, 0xfe, 0x97, 0x1d,
}

DoDad := new(struct {
	EbmlId      ebml.Id `ebml:"3f0000"`
	DoHickey    uint    `ebml:"4242"`
	ThingaMabob string  `ebml:"4243"`
	HumDinger   int     `ebml:"4244"`
})

err := ebml.Unmarshal(data, DoDad)
if err != nil {
	fmt.Println(err)
}
fmt.Printf("%v\n", DoDad)
Output:

&{0 70000 huzah -92387}

Types

type Decoder

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

A Decoder decoders EBML data from a ReadSeeker

func NewDecoder

func NewDecoder(r io.ReadSeeker) *Decoder

NewDecoder returns a new decoder that decodes from r.

func (*Decoder) Decode

func (d *Decoder) Decode(element interface{}) (err error)

Decode decodes a EBML stream into v.

type Encoder

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

An Encoder writes EBML data to an output stream.

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder returns a new encoder that writes to w.

func (*Encoder) Encode

func (enc *Encoder) Encode(element interface{}) (err error)

Encode writes the EBML binary encoding of v to an Encoder stream.

type Header struct {
	// BUG(Emery): Setting default and fallback values in
	// struct field tags is not supported.
	EbmlId             Id     `ebml:"1a45dfa3"`
	EBMLVersion        uint8  `ebml:"4286"`
	EBMLReadVersion    uint8  `ebml:"42f7"`
	EBMLMaxIDLength    uint8  `ebml:"42f2"`
	EBMLMaxSizeLength  uint8  `ebml:"42f3"`
	DocType            string `ebml:"4282"`
	DocTypeVersion     uint8  `ebml:"4287"`
	DocTypeReadVersion uint8  `ebml:"4285"`
}

Header is a struct for encoding and decoding EBML streams.

The following could be a valid top-level struct for representing Matroska streams:

type Matroska struct {
	ebml.Header
	Segment     []Segment `ebml:"18538067"`
}

You will however need to populate field values in Header to form a valid EBML document.

Example
var headerA, headerB ebml.Header
headerA.EBMLVersion = 1
headerA.EBMLReadVersion = 1
headerA.EBMLMaxIDLength = 1
headerA.EBMLMaxSizeLength = 1
headerA.DocType = "matroska"
headerA.DocTypeVersion = 1
headerA.DocTypeReadVersion = 1

b, _ := ebml.Marshal(headerA)

src := bytes.NewReader(b)
dec := ebml.NewDecoder(src)

dec.Decode(&headerB)

fmt.Printf("0x%x DeepEqual: %v", b, reflect.DeepEqual(headerA, headerB))
Output:

0x1a45dfa3a34286810142f7810142f2810142f381014282886d6174726f736b614287810142858101 DeepEqual: true

type Id

type Id uint64

Id is a type that identifies an ebml element.

func NewIdFromString

func NewIdFromString(s string) (Id, error)

NewIdFromString is a convience fuction that returns an Id for a string of hexadecimal.

func (Id) Bytes

func (id Id) Bytes() []byte

Bytes returns an Id in byte slice form

func (Id) String

func (id Id) String() string

String implements the Stringer interface, returning Id in hexadecimal form.

type Marshaler

type Marshaler interface {
	// BUG(Emery): an embedded Marshaler will trample on a struct
	MarshalEBML() (size int64, wt io.WriterTo)
}

Marshaler is the interface implemented by objects that can marshal themselves into an EBML stream. The WriterTo should only Write element data, and not the id and size header of the element. size is the length of the data that shall be written and is used to build the element header and compute the size of the parent element before it is writen to an EBML stream.

type Unmarshaler

type Unmarshaler interface {
	// BUG(Emery): an embedded Unmarshaler will trample on a struct
	UnmarshalEBML(n int64) io.ReaderFrom
}

Unmarshaler is the interface implemented by objects that can unmarshal themselves from an EBML stream. The data read into ReaderFrom will contain the data for the element being unmarshaled, and not an id or size header.

n shall be the size of the element data, and it is not the resposibility of an Unmarshaler to limit reading to n.

An Unmarshaler is usually sent to the decoding engine as a nil pointer in a struct and created when a tagged element is encountered, for this reason the UnmarshalEBML method should behave as if the Unmarshaler is at a zero value state.

Notes

Bugs

  • not caching decoder funtions for struct fields is suboptimal fieldFunc := cachedFieldDecoderTable(t)

  • Setting default and fallback values in struct field tags is not supported.

  • an embedded Marshaler will trample on a struct

  • an embedded Unmarshaler will trample on a struct

Directories

Path Synopsis
idtest is a utility for checking the validity of EBML ids
idtest is a utility for checking the validity of EBML ids

Jump to

Keyboard shortcuts

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