예제 #1
0
        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));
            }
        }
예제 #2
0
        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()));
        }