namespace Eva { public interface Term : Object { public abstract string to_string(); public abstract void encode(Erl.Buffer buffer); public static Term decode(void *buffer) { int index = 0; int version; Erl.decode_version(buffer, ref index, out version); return do_decode(buffer, ref index); } private static Term do_decode(void *buffer, ref int index) { int type, size; assert(Erl.get_type(buffer, ref index, out type, out size) == 0); switch(type) { case Erl.TermType.SMALL_INTEGER: char value; assert(Erl.decode_char(buffer, ref index, out value) == 0); return new Int((uchar)value); case Erl.TermType.INTEGER: long value; assert(Erl.decode_long(buffer, ref index, out value) == 0); return new Int(value); case Erl.TermType.FLOAT: double value; assert(Erl.decode_double(buffer, ref index, out value) == 0); return new Double(value); case Erl.TermType.ATOM: char[] value = new char[size+1]; assert(Erl.decode_atom(buffer, ref index, value) == 0); return new Atom(((string)value).ndup(size)); case Erl.TermType.SMALL_TUPLE: case Erl.TermType.LARGE_TUPLE: assert(Erl.decode_tuple_header(buffer, ref index, out size) == 0); Tuple term = new Tuple(); for(int i = 0; i < size; ++i) { term.value.add(do_decode(buffer, ref index)); } return term; case Erl.TermType.NIL: case Erl.TermType.LIST: List term = new List(); while(true) { assert(Erl.decode_list_header(buffer, ref index, out size) == 0); if(size == 0) break; for(int i = 0; i < size; ++i) { term.value.add(do_decode(buffer, ref index)); } } return term; case Erl.TermType.STRING: char[] value = new char[size+1]; assert(Erl.decode_string(buffer, ref index, value) == 0); return new String(((string)value).ndup(size)); case Erl.TermType.BINARY: char[] value = new char[size]; stdout.printf("Size: %i\n", size); long l; assert(Erl.decode_binary(buffer, ref index, value, out l) == 0); return new Binary(value); default: assert_not_reached(); } } } public class Int : Object, Term { public long value {get; construct;} public Int(long v) { Object(value: v); } public string to_string() { return value.to_string(); } public void encode(Erl.Buffer buffer) { buffer.encode_long(value); } } public class UInt : Object, Term { public ulong value {get; construct;} public UInt(ulong v) { Object(value: v); } public string to_string() { return value.to_string(); } public void encode(Erl.Buffer buffer) { buffer.encode_ulong(value); } } public class Double : Object, Term { public double value {get; construct;} public Double(double v) { Object(value: v); } public string to_string() { return value.to_string(); } public void encode(Erl.Buffer buffer) { buffer.encode_double(value); } } public class Atom : Object, Term { public string value {get; construct;} public Atom(string v) { Object(value: v); } public string to_string() { return value.to_string(); } public void encode(Erl.Buffer buffer) { buffer.encode_atom(value.to_utf8()); } } public class Tuple : Object, Term { public Gee.List value {get; construct;} public Tuple() { Gee.List list = new Gee.ArrayList(); Object(value: list); } public string to_string() { string ret = "{"; bool first = true; foreach(Term term in value) { if(first) { first = false; ret += term.to_string(); } else { ret += "," + term.to_string(); } } return ret + "}"; } public void encode(Erl.Buffer buffer) { buffer.encode_tuple_header(value.size); foreach(Term term in value) { term.encode(buffer); } } } public class List : Object, Term { public Gee.List value {get; construct;} public List() { Gee.List list = new Gee.LinkedList(); Object(value: list); } public string to_string() { string ret = "["; bool first = true; foreach(Term term in value) { if(first) { first = false; ret += term.to_string(); } else { ret += "," + term.to_string(); } } return ret + "]"; } public void encode(Erl.Buffer buffer) { if(!value.is_empty) { buffer.encode_list_header(value.size); foreach(Term term in value) { term.encode(buffer); } } buffer.encode_empty_list(); } } public class String : Object, Term { public string value {get; construct;} public String(string v) { Object(value: v); } public string to_string() { return value.to_string(); } public void encode(Erl.Buffer buffer) { buffer.encode_string(value.to_utf8()); } } public class Binary : Object, Term { public void* value {get; private set;} public long len {get; private set;} public Binary(char[] v) { value = Memory.dup(v, (uint)(sizeof(char)*v.length)); len = v.length; } public string to_string() { return "[[Binary]]"; } public void encode(Erl.Buffer buffer) { buffer.encode_binary((char*)value, len); } } }