diff --git a/README.md b/README.md index d6a11d2..2b1edc5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ Go-EBML ======= - -A marshaler and unmarshaler for [EBML](http://ebml.sourceforge.net/). +A marshaler/unmarshaler for [EBML](http://ebml.sourceforge.net/). It's quite simple to use: ```go @@ -18,16 +17,9 @@ func ExampleMarshal() { DoDad.ThingaMabob = "huzah" DoDad.HumDinger = -92387 - b, err := ebml.Marshal(*DoDad) - if err != nil { - fmt.Println(err) - } + b, _ := ebml.Marshal(*DoDad) fmt.Printf("0x%x\n", b) - err = ebml.Unmarshal(b, DoDad) - if err != nil { - fmt.Println(err) - } // Output: // 0x3f00009442428301117042438568757a6168424483fe971d } @@ -47,10 +39,7 @@ func ExampleUnmarshal() { HumDinger int `ebml:"4244"` }) - err := ebml.Unmarshal(data, DoDad) - if err != nil { - fmt.Println(err) - } + ebml.Unmarshal(data, DoDad) fmt.Printf("%v\n", DoDad) // Output: // &{0 70000 huzah -92387} @@ -59,9 +48,19 @@ func ExampleUnmarshal() { ``` +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. + + Limitations ----------- -Default values are not supported yet, as per the EBML RFC: +Default values are not implemented yet, as they are defined in the EBML RFC: > 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. diff --git a/decode.go b/decode.go index fe63b51..1b8cf2b 100644 --- a/decode.go +++ b/decode.go @@ -32,7 +32,8 @@ func readIdFrom(r io.ReadSeeker) (int, Id) { if err != nil { encError(err.Error()) } - decError(fmt.Sprintf("invalid Id at reader position %x or EBMLMaxIDLength > 4, read byte %x", p, buf[0])) + r.Read(buf) + decError(fmt.Sprintf("invalid Id at reader position 0x%x or EBMLMaxIDLength > 4, next 8 bytes 0x%0.2x", p, buf)) } var nn int nn, err = r.Read(buf) diff --git a/ebml.go b/ebml.go index 4ae7bf5..53cd1cb 100644 --- a/ebml.go +++ b/ebml.go @@ -55,7 +55,7 @@ func (id Id) Bytes() []byte { case id < 0x0800000001: l = 4 default: - panic("invalid element ID") + panic(fmt.Sprintf("invalid element ID %s", id)) } b := make([]byte, l) for l > 1 { diff --git a/ebml_test.go b/ebml_test.go index f0f44eb..aa34d0f 100644 --- a/ebml_test.go +++ b/ebml_test.go @@ -8,6 +8,7 @@ import ( "fmt" "github.com/3M3RY/go-ebml" "io" + "io/ioutil" "math/rand" "reflect" "testing" @@ -54,10 +55,6 @@ func ExampleMarshal() { } fmt.Printf("0x%x\n", b) - err = ebml.Unmarshal(b, DoDad) - if err != nil { - fmt.Println(err) - } // Output: // 0x3f00009442428301117042438568757a6168424483fe971d } @@ -136,7 +133,6 @@ func TestUint(t *testing.T) { } err = ebml.Unmarshal(buf, &out) - //err = Unmarshal(buf, &out) if err != nil && err != io.EOF { t.Fatalf("marshal int %d: %s\n buf: %x", I, err, buf) } @@ -146,3 +142,59 @@ func TestUint(t *testing.T) { } } } + +type benchTestStruct struct { + EbmlId ebml.Id `ebml:"81"` + A uint `ebml:"4011"` + B int64 `ebml:"200011"` + C int64 `ebml:"10000011"` + D string `ebml:"800000000"` +} + +func BenchmarkEncoding(b *testing.B) { + var test benchTestStruct + rand.Seed(time.Now().UnixNano()) + + test.A = uint(rand.Int63()) + test.B = rand.Int63() + test.C = 1 - rand.Int63() + test.D = "of ships and sails and whether pigs have wings" + + var err error + b.ResetTimer() + enc := ebml.NewEncoder(ioutil.Discard) + for i := 0; i < b.N; i++ { + err = enc.Encode(test) + if err != nil { + b.Fatal(err.Error()) + } + } +} + +func BenchmarkDecoding(b *testing.B) { + var control benchTestStruct + rand.Seed(time.Now().UnixNano()) + + control.A = uint(rand.Int63()) + control.B = rand.Int63() + control.C = 1 - rand.Int63() + control.D = "of ships and sails and whether pigs have wings" + + buf, err := ebml.Marshal(control) + r := bytes.NewReader(buf) + b.ResetTimer() + + dec := ebml.NewDecoder(r) + for i := 0; i < b.N; i++ { + var test benchTestStruct + err = dec.Decode(&test) + if err != nil { + b.Fatal(err.Error()) + } + + if !reflect.DeepEqual(control, test) { + b.Fatal("not equal") + } + r.Seek(0, 0) + } +}