internal static object DecodePart(byte[] encoded, ref int offset) { byte encoding_type = encoded[offset++]; switch (encoding_type) { case Constants.SMALL_INTEGER_EXT: return(encoded[offset++]); case Constants.INTEGER_EXT: return(DecodeInt(encoded, ref offset)); case Constants.STRING_EXT: ushort slen = DecodeUshort(encoded, ref offset); var cl = new List <byte>(slen); for (var i = 0; i < slen; i++) { cl.Add(encoded[offset + i]); } offset += slen; return(cl); case Constants.BINARY_EXT: int blen = (int)DecodeUint(encoded, ref offset); byte[] b = new byte[blen]; Buffer.BlockCopy(encoded, offset, b, 0, blen); offset += blen; return(b); case Constants.LIST_EXT: uint llen = DecodeUint(encoded, ref offset); var list = new ArrayList((int)llen); DecodeList(encoded, ref offset, list, llen, true); return(list); case Constants.SMALL_TUPLE_EXT: var stlen = encoded[offset++]; var st = new ETFTuple(stlen); DecodeList(encoded, ref offset, st, stlen); return(st); case Constants.LARGE_TUPLE_EXT: uint ltlen = DecodeUint(encoded, ref offset); var lt = new ETFTuple((int)ltlen); DecodeList(encoded, ref offset, lt, ltlen); return(lt); case Constants.SMALL_ATOM_EXT: var salen = encoded[offset++]; offset += salen; return(new Atom(encoded, offset - salen, salen)); case Constants.ATOM_EXT: var alen = DecodeUshort(encoded, ref offset); offset += alen; return(new Atom(encoded, offset - alen, alen)); case Constants.SMALL_BIG_EXT: return(DecodeBig(encoded, ref offset, encoded[offset++])); case Constants.LARGE_BIG_EXT: int size = (int)DecodeUint(encoded, ref offset); return(DecodeBig(encoded, ref offset, size)); case Constants.NEW_FLOAT_EXT: return(DecodeDouble(encoded, ref offset)); case Constants.FLOAT_EXT: double dret; string ds = Encoding.ASCII.GetString(encoded, offset, Constants.FLOAT_EXT_BYTES); offset += Constants.FLOAT_EXT_BYTES; NumberStyles style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite; if (Double.TryParse(ds, style, NumberFormatInfo.InvariantInfo, out dret)) { return(dret); } else { throw new EncodingError(string.Format("invalid float encoding: \"{0}\"", ds)); } case Constants.MAP_EXT: { int arity = DecodeInt(encoded, ref offset); var dict = new Dictionary <Atom, object>(arity); for (int i = 0; i < arity; i++) { var key = DecodePart(encoded, ref offset); var val = DecodePart(encoded, ref offset); dict.Add((Atom)key, val); } return(dict); } case Constants.NIL_EXT: return(new ArrayList()); default: throw new EncodingError(string.Format("invalid encoding type: {0}", encoding_type)); } }
internal static void EncodeOther(object obj, List <byte[]> parts) { byte[] b = obj as byte[]; if (b != null) { AddByte(parts, Constants.BINARY_EXT); parts.Add(UIntAsBigEndian((uint)b.Length)); parts.Add(b); return; } ETFTuple t = obj as ETFTuple; if (t != null) { if (t.Count <= Byte.MaxValue) { parts.Add(new byte[] { Constants.SMALL_TUPLE_EXT, (byte)t.Count }); } else { AddByte(parts, Constants.LARGE_TUPLE_EXT); parts.Add(UIntAsBigEndian((uint)t.Count)); } foreach (var e in t) { EncodePart(e, parts); } return; } Atom a = obj as Atom; if (a != null) { if (a.Name.Length <= Byte.MaxValue) { parts.Add(new byte[] { Constants.SMALL_ATOM_EXT, (byte)a.Name.Length }); } else { AddByte(parts, Constants.ATOM_EXT); parts.Add(UshortAsBigEndian((ushort)a.Name.Length)); } parts.Add(a.Name); return; } IList list = obj as IList; if (list != null) { if (list.Count > 0) { AddByte(parts, Constants.LIST_EXT); parts.Add(IntAsBigEndian(list.Count)); foreach (var e in list) { EncodePart(e, parts); } } AddByte(parts, Constants.NIL_EXT); return; } throw new NotSupportedException(string.Format("{0}: {1}", obj.GetType(), obj.ToString())); }