diff --git a/etf.go b/etf.go index ee7df04..f114eed 100644 --- a/etf.go +++ b/etf.go @@ -43,6 +43,13 @@ type Ref struct { Id []uint32 } +type MapEntry struct { + Key Term + Value Term +} + +type Map []MapEntry + type Function struct { Arity byte Unique [16]byte @@ -90,6 +97,7 @@ const ( ettSmallInteger = 'a' ettSmallTuple = 'h' ettString = 'k' + ettMap = 't' ) const ( @@ -129,6 +137,7 @@ var tagNames = map[byte]string{ ettSmallInteger: "SMALL_INTEGER_EXT", ettSmallTuple: "SMALL_TUPLE_EXT", ettString: "STRING_EXT", + ettMap: "MAP", } func (t Tuple) Element(i int) Term { diff --git a/read.go b/read.go index 51ea8e4..2b6a1d0 100644 --- a/read.go +++ b/read.go @@ -287,6 +287,23 @@ func (c *Context) Read(r io.Reader) (term Term, err error) { } term = tuple + case ettMap: + // $iKVKVKV… + var arity uint32 + if arity, err = ruint32(r); err != nil { + break + } + mapVal := make(Map, arity) + for i := 0; i < cap(mapVal); i++ { + if mapVal[i].Key, err = c.Read(r); err != nil { + break + } + if mapVal[i].Value, err = c.Read(r); err != nil { + break + } + } + term = mapVal + case ettList: // $lLLLL…$j var n uint32 diff --git a/write.go b/write.go index 6143096..cfcaade 100644 --- a/write.go +++ b/write.go @@ -43,6 +43,8 @@ func (c *Context) Write(w io.Writer, term interface{}) (err error) { err = c.writePid(w, v) case Tuple: err = c.writeTuple(w, v) + case Map: + err = c.writeMap(w, v) case Ref: err = c.writeRef(w, v) default: @@ -353,6 +355,32 @@ func (c *Context) writeTuple(w io.Writer, tuple Tuple) (err error) { return } +func (c *Context) writeMap(w io.Writer, theMap Map) (err error) { + n := len(theMap) + _, err = w.Write([]byte{ + ettMap, + byte(n >> 24), + byte(n >> 16), + byte(n >> 8), + byte(n), + }) + + if err != nil { + return + } + + for _, v := range theMap { + if err = c.Write(w, v.Key); err != nil { + return + } + if err = c.Write(w, v.Value); err != nil { + return + } + } + + return +} + func reverse(b []byte) []byte { size := len(b) hsize := size >> 1