Example #1
0
        private IEnumerable <IErlObject> enumErlResponseTuple(ErlTuple tuple, bool singleKey)
        {
            if (singleKey)
            {
                foreach (var elm in tuple)
                {
                    yield return(elm);
                }

                yield break;
            }

            for (var i = 0; i < tuple.Count; i++)
            {
                var elm = tuple[i];
                if (i == 1)
                {
                    var ktuple = elm as ErlTuple;
                    if (ktuple == null)
                    {
                        throw new ErlDataAccessException(StringConsts.ERL_DS_INTERNAL_MAPPING_ERROR + "key tuple is missing");
                    }

                    foreach (var keye in ktuple)
                    {
                        yield return(keye);
                    }
                    continue;
                }
                yield return(elm);
            }
        }
Example #2
0
 private void sendRpcReply(ErlPid from, ErlRef eref, IErlObject reply)
 {
     if (from.Empty)
     {
         return;
     }
     Node.Send(from, ErlTuple.Create(eref, reply));
 }
Example #3
0
        private void threadSpinCore()
        {
            // For Erlang I/O protocol see:
            // http://erlang.org/doc/apps/stdlib/io_protocol.html

            var patterns = new ErlPatternMatcher
            {
                { "{'$gen_call', {~v::pid(), ~v::ref()}, {call, ~v::atom(), ~v::atom(), ~v::list(), ~v}}".ErlArgs(P, R, M, F, A, G),
                  (_p, _t, b, a) => rpcCall(
                      b.Cast <ErlPid>(P), b.Cast <ErlRef>(R),
                      b.Cast <ErlAtom>(M), b.Cast <ErlAtom>(F), b.Cast <ErlList>(A), b[G]) },
                { "{'$gen_cast', {cast, ~v::atom(), ~v::atom(), ~v::list(), ~v}}".ErlArgs(M, F, A, G),
                  (_p, _t, b, a) => rpcCall(
                      ErlPid.Null, ErlRef.Null,
                      b.Cast <ErlAtom>(M), b.Cast <ErlAtom>(F), b.Cast <ErlList>(A), b[G]) },
                { "{_, {~v::pid(), ~v::ref()}, _Cmd}".ErlArgs(P, R),
                  (_p, _t, b, a) =>
                  ErlTuple.Create(b[P], b[R], ErlTuple.Create(ConstAtoms.Error, ConstAtoms.Unsupported)) },
            };

            while (m_Active)
            {
                Tuple <IErlObject, int> res = Self.ReceiveMatch(patterns, 1500);

                switch (res.Item2)
                {
                case -2: /* timeout  */
                    break;

                case -1: /* no match */
                    App.Log.Write(Log.MessageType.Warning,
                                  StringConsts.ERL_INVALID_RPC_REQUEST_ERROR, res.Item1.ToString());
                    break;

                default:
                    if (res.Item1 == null)
                    {
                        break;
                    }
                    var t     = (ErlTuple)res.Item1;
                    var pid   = t.Cast <ErlPid>(0);
                    var eref  = t.Cast <ErlRef>(1);
                    var reply = t[2];
                    sendRpcReply(pid, eref, reply);
                    break;
                }
            }

            App.Log.Write(
                Log.MessageType.Info, StringConsts.ERL_STOPPING_SERVER.Args(Node.NodeName, "RPC"));

            m_Thread = null;
        }
Example #4
0
        public void ErlFormatTest()
        {
            var tests = new Dictionary <string, ErlList>
            {
                { "abc 10.5", new ErlList("abc ~w.~w", 10, 5) },
                { "xx 8", new ErlList("xx ~i~w", 12, 8) },
                { "~z", new ErlList("~~z", 16) },
                { "a 16", new ErlList("~c ~w", (byte)'a', 16) },
                { "xyz 12\n", new ErlList("xyz ~10.6.B~n", 12) },
                { "x~y21", new ErlList("x~~y~w1", 2) },
                { "{ok, A}", new ErlList("{ok, ~v}", "A") },
                { "{ok, A}.", new ErlList("{ok, ~v}.", new ErlAtom("A")) },
                { "{ok, A} ", new ErlList("{ok, ~v} ", new ErlString("A")) },
                { "{ok, A}  ", new ErlList("{ok, ~v}  ", new ErlVar("A")) },
                {
                    "{ok, A::a()}",
                    new ErlList("{ok, ~v::a()}", new ErlVar("A", ErlTypeOrder.ErlLong))
                },
                { "{ok, A::int()}", new ErlList("{ok, ~v}", new ErlVar("A", ErlTypeOrder.ErlLong)) },
            };

            foreach (var t in tests)
            {
                Assert.AreEqual(t.Key, ErlObject.Format(t.Value),
                                "Error in test: {0} <- format({1})".Args(t.Key, t.Value.ToString()));
            }

            var failTests = new List <ErlList>
            {
                new ErlList("abc ~w.~w"),
                new ErlList("xx ~i~w", 12),
                new ErlList("~y", 12),
            };

            foreach (var t in failTests)
            {
                Assert.Throws <ErlException>(
                    () => ErlObject.Format(t), "Errorneously formatted term: {0}".Args(t));
            }

            var V        = new ErlVar("V", ErlTypeOrder.ErlLong);
            var expected = new ErlTuple(new ErlAtom("ok"), V).ToString();

            Assert.AreEqual(expected, "{ok, V::int()}".ToErlObject().ToString());
            Assert.AreEqual(expected, "{ok, ~w}".ToErlObject(V).ToString());
        }
Example #5
0
        /// <summary>
        /// Maps ErlRow to CLR row supplied by schema, either Dynamic or TypedRow
        /// </summary>
        public Row ErlTupleToRow(string schemaName, ErlTuple tuple, Schema schema)
        {
            var singleKey = schema.ExtraData[SCHEMA_KEY_COUNT].AsInt(0) < 2;

            var row = Row.MakeRow(schema, schema.TypedRowType);

            var i = -1;

            foreach (var elm in enumErlResponseTuple(tuple, singleKey))
            {
                i++;
                if (i == 0)
                {
                    var thisname = tuple[0].ValueAsString;
                    if (!schemaName.EqualsOrdSenseCase(thisname))
                    {
                        throw new ErlDataAccessException(StringConsts.ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR.Args(thisname, schemaName));
                    }
                    continue;
                }

                //map fields now
                if (i - 1 >= schema.FieldCount)
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_CRUD_RESP_SCH_FLD_COUNT_ERROR.Args(schemaName, schema.Name));
                }
                var fdef = schema[i - 1];
                var atr  = fdef[m_Store.TargetName];

                var erlType = atr.BackendType;
                if (erlType.IsNullOrWhiteSpace())
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_INTERNAL_MAPPING_ERROR + "fielddef('{0}') has no backend type".Args(fdef.Name));
                }

                var clrValue = ErlToClrValue(elm, schema, fdef, m_Store.TargetName, tuple);
                row.SetFieldValue(fdef, clrValue);
            }

            return(row);
        }
Example #6
0
        private IErlObject rpcCall(ErlPid from, ErlRef eref,
                                   ErlAtom mod, ErlAtom fun, ErlList args, IErlObject groupLeader)
        {
            // We spawn a new task, so that RPC calls wouldn't block the RPC server thread
            Task.Factory.StartNew(() =>
            {
                var type = Type.GetType(mod);

                if (type == null)
                {
                    sendRpcReply(from, eref,
                                 ErlTuple.Create(ConstAtoms.Error, "unknown type: {0}".Args(mod)));
                    return;
                }

                // TODO: add LRU caching
                //var method = type.GetMethod(fun.Value, BindingFlags.Static | BindingFlags.Public);

                string methodName = fun.Value;

                if (args.Count == 0)
                {
                    var pi = type.GetProperty(fun, BindingFlags.Static | BindingFlags.Public);
                    if (pi != null)
                    {
                        try
                        {
                            var result = pi.GetValue(null, null);
                            sendRpcReply(from, eref,
                                         ErlTuple.Create(ConstAtoms.Ok, result.ToErlObject()));
                        }
                        catch (Exception e)
                        {
                            sendRpcReply(from, eref,
                                         ErlTuple.Create(ConstAtoms.Error, new ErlString(e.Message)));
                        };
                        return;
                    }
                }

                var mi = type.GetMethods(BindingFlags.Static | BindingFlags.Public)
                         .Where(m => m.Name == methodName && m.GetParameters().Count() == args.Count)
                         .FirstOrDefault();

                if (mi == null)
                {
                    sendRpcReply(from, eref,
                                 ErlTuple.Create(ConstAtoms.Error, "unknown method: {0}".Args(fun)));
                    return;
                }

                var pars = mi.GetParameters();

                var margs = new object[pars.Length];

                for (int i = 0; i < pars.Length; i++)
                {
                    var par  = pars[i];
                    var val  = args[i];
                    margs[i] = val.AsType(par.ParameterType);
                }

                try
                {
                    var result = mi.Invoke(type, margs);
                    sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Ok, result.ToErlObject()));
                }
                catch (Exception e)
                {
                    sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Error, new ErlString(e.Message)));
                }
            });
            return((IErlObject)null);
        }
Example #7
0
        public void ErlTupleTest()
        {
            var l = new ErlTuple("test", 1, 1.1, true, (byte)255, 'x', new ErlAtom("a"));
            var r = new ErlTuple("test", 1, 1.1, true, (byte)255, 'x', new ErlAtom("a"));

            Assert.AreEqual(7, l.Count);
            Assert.AreEqual(ErlTypeOrder.ErlString, l[0].TypeOrder);
            Assert.AreEqual("test", l[0].ValueAsString);
            Assert.AreEqual(ErlTypeOrder.ErlLong, l[1].TypeOrder);
            Assert.AreEqual(1, l[1].ValueAsInt);
            Assert.AreEqual(ErlTypeOrder.ErlDouble, l[2].TypeOrder);
            Assert.AreEqual(1.1, l[2].ValueAsDouble);
            Assert.AreEqual(ErlTypeOrder.ErlBoolean, l[3].TypeOrder);
            Assert.AreEqual(true, l[3].ValueAsBool);
            Assert.AreEqual(ErlTypeOrder.ErlByte, l[4].TypeOrder);
            Assert.AreEqual(255, l[4].ValueAsInt);
            Assert.AreEqual(ErlTypeOrder.ErlByte, l[5].TypeOrder);
            Assert.AreEqual('x', l[5].ValueAsChar);
            Assert.AreEqual(ErlTypeOrder.ErlAtom, l[6].TypeOrder);
            Assert.AreEqual("a", l[6].ValueAsString);

            Assert.IsTrue(l.Matches(r));
            Assert.AreEqual(new ErlVarBind(), l.Match(r));

            Assert.AreEqual(l, r);
            Assert.IsTrue(l.Equals(r));
            Assert.AreEqual("{\"test\",1,1.1,true,255,120,a}", l.ToString());
            Assert.IsFalse(l.IsScalar);
            Assert.AreEqual(ErlTypeOrder.ErlTuple, l.TypeOrder);

            IErlObject temp = null;

            Assert.IsFalse(l.Subst(ref temp, new ErlVarBind()));
            Assert.AreEqual(1, l.Visit(0, (acc, o) => acc + (o is ErlAtom ? 1 : 0)));
            Assert.IsTrue(new ErlTuple(new ErlVar(X), true, 1).Subst(ref temp, new ErlVarBind {
                { X, new ErlLong(10) }
            }));
            Assert.AreEqual("{10,true,1}", temp.ToString());

            var d  = new DateTime(2013, 1, 2);
            var ts = new TimeSpan(1, 2, 3);

            Assert.DoesNotThrow(() => { var x = l.ValueAsObject; });
            Assert.AreEqual(1, new ErlList("1")[0].ValueAsInt);
            Assert.AreEqual(1, new ErlList("1")[0].ValueAsLong);
            Assert.AreEqual(1, new ErlList("1")[0].ValueAsDecimal);
            Assert.AreEqual(d, new ErlList(d.ToString())[0].ValueAsDateTime);
            Assert.AreEqual(ts, new ErlList(ts.ToString())[0].ValueAsTimeSpan);
            Assert.AreEqual(1.0, new ErlList("1.0")[0].ValueAsDouble);
            Assert.AreEqual("a", new ErlList("a")[0].ValueAsString);
            Assert.IsTrue(new ErlList("true")[0].ValueAsBool);
            Assert.IsFalse(new ErlList("xxxx")[0].ValueAsBool);

            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsInt; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsLong; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsDecimal; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsDateTime; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsTimeSpan; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsDouble; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsString; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsBool; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsChar; });
            Assert.Throws <ErlIncompatibleTypesException>(() => { var x = l.ValueAsByteArray; });


            List <IErlObject> s = l;

            Assert.AreEqual(l.Value, s);

            Assert.IsFalse(new ErlList(1, 1.0, "a").Equals(new ErlTuple(1, 1.0, "a")));
            Assert.IsFalse(new ErlList(1, 1.0, "a") == new ErlTuple(1, 1.0, "a"));
            Assert.IsTrue(new ErlList(1, 1.0, "a") == new ErlList(1, 1.0, "a"));
        }
Example #8
0
        public void ErlTermSerializeTest()
        {
            {
                var b  = new byte[] { 131, 100, 0, 3, 97, 98, 99 };
                var t  = new ErlAtom("abc");
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 109, 0, 0, 0, 3, 1, 2, 3 };
                var t  = new ErlBinary(new byte[] { 1, 2, 3 });
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b1  = new byte[] { 131, 100, 0, 4, 116, 114, 117, 101 };
                var t1  = new ErlBoolean(true);
                var os1 = new ErlOutputStream(t1);
                Aver.IsTrue(b1.MemBufferEquals(os1.GetBuffer().TakeWhile((_, i) => i < b1.Length).ToArray()));
                var es1 = new ErlInputStream(b1);
                Aver.AreEqual(t1, es1.Read());

                var b2  = new byte[] { 131, 100, 0, 5, 102, 97, 108, 115, 101 };
                var t2  = new ErlBoolean(false);
                var os2 = new ErlOutputStream(t2);
                Aver.IsTrue(b2.MemBufferEquals(os2.GetBuffer().TakeWhile((_, i) => i < b2.Length).ToArray()));
                var es2 = new ErlInputStream(b2);
                Aver.AreEqual(t2, es2.Read());
            }
            {
                var b  = new byte[] { 131, 97, 127 };
                var t  = new ErlByte(127);
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 70, 64, 36, 62, 249, 219, 34, 208, 229 };
                var t  = new ErlDouble(10.123);
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 108, 0, 0, 0, 2, 107, 0, 1, 1, 107, 0, 1, 2, 106 };
                var t  = new ErlList(new ErlList(1), new ErlList(2));
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 108, 0, 0, 0, 2, 108, 0, 0, 0, 2, 97, 1, 107, 0, 1, 2, 106, 107, 0, 1, 3, 106 };
                var t  = new ErlList(new ErlList(1, new ErlList(2)), new ErlList(3));
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b = new byte[] { 131, 108, 0, 0, 0, 3, 97, 1, 70, 64, 36, 61, 112, 163, 215, 10, 61, 108, 0, 0, 0, 2,
                                     100, 0, 4, 116, 114, 117, 101, 107, 0, 1, 97, 106, 106 };
                var t  = new ErlList(1, 10.12, new ErlList(true, "a"));
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b = new byte[] {
                    131, 108, 0, 0, 0, 3, 97, 23, 97, 4, 104, 1, 108, 0, 0, 0, 1, 104, 2, 109, 0, 0, 0, 5, 101, 118, 101,
                    110, 116, 104, 1, 108, 0, 0, 0, 2, 104, 2, 109, 0, 0, 0, 10, 102, 108, 101, 101, 116, 95, 104, 97,
                    115, 104, 109, 0, 0, 0, 36, 97, 54, 97, 50, 50, 100, 49, 52, 45, 56, 52, 56, 51, 45, 52, 49, 102, 99,
                    45, 97, 52, 54, 98, 45, 50, 56, 51, 98, 57, 55, 55, 55, 99, 50, 97, 50, 104, 2, 109, 0, 0, 0, 4, 116,
                    121, 112, 101, 109, 0, 0, 0, 13, 102, 108, 101, 101, 116, 95, 99, 104, 97, 110, 103, 101, 100,
                    106, 106, 106
                };
                var t = ErlObject.Parse("[23,4,{[{<<\"event\">>," +
                                        "{[{<<\"fleet_hash\">>,<<\"a6a22d14-8483-41fc-a46b-283b9777c2a2\">>}," +
                                        "{<<\"type\">>,<<\"fleet_changed\">>}]}}]}]");
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b1  = new byte[] { 131, 98, 255, 255, 255, 251 };
                var t1  = new ErlLong(-5);
                var os1 = new ErlOutputStream(t1);
                Aver.IsTrue(b1.MemBufferEquals(os1.GetBuffer().TakeWhile((_, i) => i < b1.Length).ToArray()));
                var es1 = new ErlInputStream(b1);
                Aver.AreEqual(t1, es1.Read());

                var b2  = new byte[] { 131, 97, 5 };
                var t2  = new ErlLong(5);
                var os2 = new ErlOutputStream(t2);
                Aver.IsTrue(b2.MemBufferEquals(os2.GetBuffer().TakeWhile((_, i) => i < b2.Length).ToArray()));
                var es2 = new ErlInputStream(b2);
                Aver.AreEqual(t2, es2.Read());

                var b3  = new byte[] { 131, 98, 0, 16, 0, 0 };
                var t3  = new ErlLong(1024 * 1024);
                var os3 = new ErlOutputStream(t3);
                Aver.IsTrue(b3.MemBufferEquals(os3.GetBuffer().TakeWhile((_, i) => i < b3.Length).ToArray()));
                var es3 = new ErlInputStream(b3);
                Aver.AreEqual(t3, es3.Read());

                var b4  = new byte[] { 131, 110, 6, 0, 0, 0, 0, 0, 0, 4 };
                var t4  = new ErlLong(1024L * 1024 * 1024 * 1024 * 4);
                var os4 = new ErlOutputStream(t4);
                Aver.IsTrue(b4.MemBufferEquals(os4.GetBuffer().TakeWhile((_, i) => i < b4.Length).ToArray()));
                var es4 = new ErlInputStream(b4);
                Aver.AreEqual(t4, es4.Read());

                var b5  = new byte[] { 131, 110, 8, 1, 0, 0, 0, 0, 0, 0, 0, 128 };
                var t5  = new ErlLong(1L << 63);
                var os5 = new ErlOutputStream(t5);
                Aver.IsTrue(b5.MemBufferEquals(os5.GetBuffer().TakeWhile((_, i) => i < b5.Length).ToArray()));
                var es5 = new ErlInputStream(b5);
                Aver.AreEqual(t5, es5.Read());

                var b6  = new byte[] { 131, 110, 8, 1, 0, 0, 0, 0, 0, 0, 0, 128 };
                var t6  = new ErlLong(-1L << 63);
                var os6 = new ErlOutputStream(t6);
                Aver.IsTrue(b6.MemBufferEquals(os6.GetBuffer().TakeWhile((_, i) => i < b6.Length).ToArray()));
                var es6 = new ErlInputStream(b6);
                Aver.AreEqual(t6, es6.Read());

                var b7  = new byte[] { 131, 110, 8, 0, 255, 255, 255, 255, 255, 255, 255, 255 };
                var es7 = new ErlInputStream(b7);
                var t7  = new ErlLong(-1);
                Aver.AreEqual(t7, es7.Read());
                var bi7 = new byte[] { 131, 98, 255, 255, 255, 255 };
                var os7 = new ErlOutputStream(t7);
                Aver.IsTrue(bi7.MemBufferEquals(os7.GetBuffer().TakeWhile((_, i) => i < bi7.Length).ToArray()));
            }
            {
                var b  = new byte[] { 131, 103, 100, 0, 7, 98, 64, 112, 105, 112, 105, 116, 0, 0, 0, 38, 0, 0, 0, 0, 1 };
                var t  = new ErlPid("b@pipit", 38, 0, 1);
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 102, 100, 0, 7, 98, 64, 112, 105, 112, 105, 116, 0, 0, 0, 38, 1 };
                var t  = new ErlPort("b@pipit", 38, 1);
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 114, 0, 3, 100, 0, 7, 98, 64, 112, 105, 112, 105, 116, 1, 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, 0, 0 };
                var t  = new ErlRef("b@pipit", 181, 0, 0, 1);
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 107, 0, 3, 115, 116, 114 };
                var t  = new ErlString("str");
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 104, 3, 97, 1, 100, 0, 1, 97, 104, 2, 97, 10, 70, 63, 241, 247, 206, 217, 22, 135, 43 };
                var t  = new ErlTuple(1, new ErlAtom("a"), new ErlTuple(10, 1.123));
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
            {
                var b = new byte[] { 131, 116, 0, 0, 0, 2, 100, 0, 1, 97, 97, 1, 107, 0, 3, 115, 116, 114, 70, 64, 0, 0, 0, 0, 0, 0, 0 };
                var t = new ErlMap {
                    { new ErlAtom("a"), 1.ToErlObject() },
                    { new ErlString("str"), new ErlDouble(2.0) }
                };
                var os = new ErlOutputStream(t);
                Aver.IsTrue(b.MemBufferEquals(os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray()));
                var es = new ErlInputStream(b);
                Aver.AreEqual(t, es.Read());
            }
        }
Example #9
0
        /// <summary>
        /// Convert an Erlang hierarchical term representing a schema to a Row.
        /// </summary>
        /// <param name="row">Row to update</param>
        /// <param name="data">
        ///   Data to update row with.
        ///   The data must be in the form {SchemaName::atom, [{FieldName::atom(), Value}]}.
        /// </param>
        /// <param name="schema">Alternative schema to use in place of row.Schema</param>
        /// <param name="targetName">Name of the target for looking up field attributes</param>
        /// <param name="schemaName">Alternative name of the top-most 'SchemaName' atom used in the "data".</param>
        /// <param name="knownSchemas">List of known schemas to use when initializing a field a DynamicRow type.</param>
        public static void Update(this Row row, IErlObject data, Schema schema = null, string targetName = null,
            string schemaName = null, Registry<Schema> knownSchemas = null)
        {
            if (schema == null)
            schema = row.Schema;

              if (schemaName == null)
            schemaName = schema.Name;

              if (data == null)
            data = new ErlTuple(new ErlAtom(schemaName), new ErlList());

              // Input data must be in the form: {SchemaName::atom(), [{FieldName::atom(), Value}]}
              // where Value can be any primitive value or a hierarchical value with another Row type.
              if (!checkKeyValueTuple(data) || ((ErlTuple)data)[1].TypeOrder != ErlTypeOrder.ErlList)
            throw new ErlDataAccessException(
              StringConsts.ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR.Args(data.ToString(), schema.Name));

              var dataList = ((ErlTuple)data)[1] as ErlList;

              // Make sure that the first element of the tuple matches the schema name
              if (!((ErlTuple)data)[0].ValueAsString.Equals(schemaName))
            throw new ErlDataAccessException(
              StringConsts.ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR.Args(data.ToString(), schema.Name));

              // Contains a set of field names that are present in configuration
              var presentFieldNames = new HashSet<string>();
              foreach (var item in dataList.Where(checkKeyValueTuple).Cast<ErlTuple>())
            presentFieldNames.Add(item[0].ValueAsString);

              ErlList newList = null;

              foreach (var fld in schema.Where(fd => typeof(Row).IsAssignableFrom(fd.Type)))
            if (!presentFieldNames.Contains(fld.Name))
            {
              if (newList == null)
            newList = (ErlList)dataList.Clone();
              // Add: {FieldName::atom(), []}
              newList.Add(new ErlTuple(new ErlAtom(fld.Name), new ErlList()));
            }

              // If no new items were added to the list use current list:
              if (newList == null) newList = dataList;

              foreach (var item in newList.Where(checkKeyValueTuple).Cast<ErlTuple>())
              {
            var name  = item[0].ValueAsString;
            var value = item[1];
            var fdef  = schema[name];
            var attr  = fdef[targetName];

            if (!attr.Visible || (attr.Metadata != null && attr.Metadata.Navigate("$readonly|$read-only|$read_only").ValueAsBool()))
              continue;

            // If this field is defined in the schema as a Row type, then we need to descend into the
            // value's hierarchical structure and treat it as a nested row
            if (typeof(Row).IsAssignableFrom(fdef.Type))
            {
              // Get the row associated
              Schema chldSch;
              var chldRow = row[fdef.Order] as Row;

              // If the row has a field of Row type initialized, use its Schema value.
              if (chldRow != null)
            chldSch = chldRow.Schema;
              else
              {
            // Otherwise lookup the schema from the given registry
            if (!knownSchemas.TryGetValue(name, out chldSch))
              throw new ErlDataAccessException(
                StringConsts.ERL_DS_SCHEMA_NOT_KNOWN_ERROR.Args(name, data.ToString()));
            // Construct the field's value as dynmiac row of the looked up schema type
            chldRow = new DynamicRow(chldSch);
            chldRow.ApplyDefaultFieldValues();
            row[fdef.Order] = chldRow;
              }

              if (value.TypeOrder != ErlTypeOrder.ErlList)
            throw new ErlDataAccessException(
              StringConsts.ERL_DS_SCHEMA_INVALID_VALUE_ERROR.Args(chldSch.Name, value));

              // Recursively update the field's value from given data by using the field's schema:
              chldRow.Update(item, chldSch, targetName, knownSchemas: knownSchemas);
            }
            else
            {
              // This is a primitive value type
              var clr = SchemaMap.ErlToClrValue(value, schema, fdef, null, data);
              row.SetFieldValue(fdef, clr);
            }
              }
        }
Example #10
0
        /// <summary>
        /// Convert an Erlang hierarchical term representing a schema to a Row.
        /// </summary>
        /// <param name="row">Row to update</param>
        /// <param name="data">
        ///   Data to update row with.
        ///   The data must be in the form {SchemaName::atom, [{FieldName::atom(), Value}]}.
        /// </param>
        /// <param name="schema">Alternative schema to use in place of row.Schema</param>
        /// <param name="targetName">Name of the target for looking up field attributes</param>
        /// <param name="schemaName">Alternative name of the top-most 'SchemaName' atom used in the "data".</param>
        /// <param name="knownSchemas">List of known schemas to use when initializing a field a DynamicRow type.</param>
        public static void Update(this Row row, IErlObject data, Schema schema = null, string targetName = null,
                                  string schemaName = null, Registry <Schema> knownSchemas = null)
        {
            if (schema == null)
            {
                schema = row.Schema;
            }

            if (schemaName == null)
            {
                schemaName = schema.Name;
            }

            if (data == null)
            {
                data = new ErlTuple(new ErlAtom(schemaName), new ErlList());
            }

            // Input data must be in the form: {SchemaName::atom(), [{FieldName::atom(), Value}]}
            // where Value can be any primitive value or a hierarchical value with another Row type.
            if (!checkKeyValueTuple(data) || ((ErlTuple)data)[1].TypeOrder != ErlTypeOrder.ErlList)
            {
                throw new ErlDataAccessException(
                          StringConsts.ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR.Args(data.ToString(), schema.Name));
            }

            var dataList = ((ErlTuple)data)[1] as ErlList;

            // Make sure that the first element of the tuple matches the schema name
            if (!((ErlTuple)data)[0].ValueAsString.Equals(schemaName))
            {
                throw new ErlDataAccessException(
                          StringConsts.ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR.Args(data.ToString(), schema.Name));
            }

            // Contains a set of field names that are present in configuration
            var presentFieldNames = new HashSet <string>();

            foreach (var item in dataList.Where(checkKeyValueTuple).Cast <ErlTuple>())
            {
                presentFieldNames.Add(item[0].ValueAsString);
            }

            ErlList newList = null;

            foreach (var fld in schema.Where(fd => typeof(Row).IsAssignableFrom(fd.Type)))
            {
                if (!presentFieldNames.Contains(fld.Name))
                {
                    if (newList == null)
                    {
                        newList = (ErlList)dataList.Clone();
                    }
                    // Add: {FieldName::atom(), []}
                    newList.Add(new ErlTuple(new ErlAtom(fld.Name), new ErlList()));
                }
            }

            // If no new items were added to the list use current list:
            if (newList == null)
            {
                newList = dataList;
            }

            foreach (var item in newList.Where(checkKeyValueTuple).Cast <ErlTuple>())
            {
                var name  = item[0].ValueAsString;
                var value = item[1];
                var fdef  = schema[name];
                var attr  = fdef[targetName];

                if (!attr.Visible || (attr.Metadata != null && attr.Metadata.Navigate("$readonly|$read-only|$read_only").ValueAsBool()))
                {
                    continue;
                }

                // If this field is defined in the schema as a Row type, then we need to descend into the
                // value's hierarchical structure and treat it as a nested row
                if (typeof(Row).IsAssignableFrom(fdef.Type))
                {
                    // Get the row associated
                    Schema chldSch;
                    var    chldRow = row[fdef.Order] as Row;

                    // If the row has a field of Row type initialized, use its Schema value.
                    if (chldRow != null)
                    {
                        chldSch = chldRow.Schema;
                    }
                    else
                    {
                        // Otherwise lookup the schema from the given registry
                        if (!knownSchemas.TryGetValue(name, out chldSch))
                        {
                            throw new ErlDataAccessException(
                                      StringConsts.ERL_DS_SCHEMA_NOT_KNOWN_ERROR.Args(name, data.ToString()));
                        }
                        // Construct the field's value as dynmiac row of the looked up schema type
                        chldRow = new DynamicRow(chldSch);
                        chldRow.ApplyDefaultFieldValues();
                        row[fdef.Order] = chldRow;
                    }

                    if (value.TypeOrder != ErlTypeOrder.ErlList)
                    {
                        throw new ErlDataAccessException(
                                  StringConsts.ERL_DS_SCHEMA_INVALID_VALUE_ERROR.Args(chldSch.Name, value));
                    }

                    // Recursively update the field's value from given data by using the field's schema:
                    chldRow.Update(item, chldSch, targetName, knownSchemas: knownSchemas);
                }
                else
                {
                    // This is a primitive value type
                    var clr = SchemaMap.ErlToClrValue(value, schema, fdef, null, data);
                    row.SetFieldValue(fdef, clr);
                }
            }
        }
Example #11
0
    /// <summary>
    /// Compile a string fmt into an Erlang term
    /// </summary>
    internal static IErlObject Parse(
        string fmt, ref int pos, ref int argc, params object[] args)
    {
      var items = new List<IErlObject>();
      IErlObject result = null;
      pos = skipWSAndComments(fmt, pos);

      if (pos < fmt.Length)
      {
        switch (fmt[pos++])
        {
          case '{':
            if (State.Ok != pTuple(fmt, ref pos, ref items, ref argc, args))
              throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "tuple", pos);
            result = new ErlTuple(items, false);
            break;

          case '[':
            if (fmt[pos] == ']')
            {
              result = new ErlList();
              pos++;
              break;
            }
            else if (State.Ok == pList(fmt, ref pos, ref items, ref argc, args))
            {
              result = new ErlList(items, false);
              break;
            }
            throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "list", pos);

          case '$': /* char-value? */
            result = new ErlByte(Convert.ToByte(fmt[pos++]));
            break;

          case '~':
            if (State.Ok != pFormat(fmt, ref pos, ref items, ref argc, args))
              throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "term", pos);
            result = items[0];
            break;

          default:
            char c = fmt[--pos];
            if (char.IsLower(c))
            {         /* atom  ? */
              string s = pAtom(fmt, ref pos);
              result = createAtom(s);
            }
            else if (char.IsUpper(c) || c == '_')
            {
              result = pVariable(fmt, ref pos);
            }
            else if (char.IsDigit(c) || c == '-')
            {    /* integer/float ? */
              string s = pDigit(fmt, ref pos);
              if (s.IndexOf('.') < 0)
                result = new ErlLong(long.Parse(s, CultureInfo.InvariantCulture));
              else
                result = new ErlDouble(double.Parse(s, CultureInfo.InvariantCulture));
            }
            else if (c == '"')
            {      /* string ? */
              string s = pString(fmt, ref pos);
              result = new ErlString(s);
            }
            else if (c == '\'')
            {     /* quoted atom ? */
              string s = pQuotedAtom(fmt, ref pos);
              result = createAtom(s);
            }
            break;
        }
      }

      if (result == null)
        throw new ErlException(StringConsts.ERL_INVALID_VALUE_ERROR.Args(fmt));

      return result;
    }
Example #12
0
        /// <summary>
        /// Compile a string fmt into an Erlang term
        /// </summary>
        internal static IErlObject Parse(
            string fmt, ref int pos, ref int argc, params object[] args)
        {
            var        items  = new List <IErlObject>();
            IErlObject result = null;

            pos = skipWSAndComments(fmt, pos);

            if (pos < fmt.Length)
            {
                switch (fmt[pos++])
                {
                case '{':
                    if (State.Ok != pTuple(fmt, ref pos, ref items, ref argc, args))
                    {
                        throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "tuple", pos);
                    }
                    result = new ErlTuple(items, false);
                    break;

                case '[':
                    if (fmt[pos] == ']')
                    {
                        result = new ErlList();
                        pos++;
                        break;
                    }
                    else if (State.Ok == pList(fmt, ref pos, ref items, ref argc, args))
                    {
                        result = new ErlList(items, false);
                        break;
                    }
                    throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "list", pos);

                case '$':     /* char-value? */
                    result = new ErlByte(Convert.ToByte(fmt[pos++]));
                    break;

                case '~':
                    if (State.Ok != pFormat(fmt, ref pos, ref items, ref argc, args))
                    {
                        throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "term", pos);
                    }
                    result = items[0];
                    break;

                default:
                    char c = fmt[--pos];
                    if (char.IsLower(c))
                    {             /* atom  ? */
                        string s = pAtom(fmt, ref pos);
                        result = createAtom(s);
                    }
                    else if (char.IsUpper(c) || c == '_')
                    {
                        result = pVariable(fmt, ref pos);
                    }
                    else if (char.IsDigit(c) || c == '-')
                    {        /* integer/float ? */
                        string s = pDigit(fmt, ref pos);
                        if (s.IndexOf('.') < 0)
                        {
                            result = new ErlLong(long.Parse(s, CultureInfo.InvariantCulture));
                        }
                        else
                        {
                            result = new ErlDouble(double.Parse(s, CultureInfo.InvariantCulture));
                        }
                    }
                    else if (c == '"')
                    {          /* string ? */
                        string s = pString(fmt, ref pos);
                        result = new ErlString(s);
                    }
                    else if (c == '\'')
                    {         /* quoted atom ? */
                        string s = pQuotedAtom(fmt, ref pos);
                        result = createAtom(s);
                    }
                    break;
                }
            }

            if (result == null)
            {
                throw new ErlException(StringConsts.ERL_INVALID_VALUE_ERROR.Args(fmt));
            }

            return(result);
        }
Example #13
0
        /// <summary>
        /// Converts CLR row data into ErlTuple
        /// </summary>
        public ErlTuple RowToErlTuple(Row row, bool keysOnly = false)
        {
            var result = new ErlTuple();

            result.Add(new ErlAtom(row.Schema.Name));

            var keys = new List <IErlObject>();

            foreach (var def in row.Schema)
            {
                var atr = def[m_Store.TargetName];

                if (keysOnly && !atr.Key)
                {
                    break;
                }

                if (keys != null && !atr.Key)
                {
                    if (keys.Count > 1)
                    {
                        result.Add(new ErlTuple(keys, false));
                    }
                    else
                    {
                        foreach (var key in keys)
                        {
                            result.Add(key);
                        }
                    }
                    keys = null;
                }


                IErlObject erlValue = ErlAtom.Undefined;

                var clrValue = row.GetFieldValue(def);
                if (clrValue != null)
                {
                    erlValue = ClrToErlValue(atr.BackendType, clrValue);
                }

                if (keys != null)
                {
                    keys.Add(erlValue);
                }
                else
                {
                    result.Add(erlValue);
                }
            }

            if (keys != null)
            {
                if (keys.Count > 1)
                {
                    result.Add(new ErlTuple(keys, false));
                }
                else
                {
                    foreach (var key in keys)
                    {
                        result.Add(key);
                    }
                }
            }

            return(result);
        }
Example #14
0
        /// <summary>
        /// Compile a string fmt into an Erlang term
        /// </summary>
        internal static IErlObject Parse(
            string fmt, ref int pos, ref int argc, params object[] args)
        {
            var items = new List<IErlObject>();
              IErlObject result = null;
              pos = skipWSAndComments(fmt, pos);

              if (pos < fmt.Length)
              {
            switch (fmt[pos++])
            {
              case '{':
            if (State.Ok != pTuple(fmt, ref pos, ref items, ref argc, args))
              throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "tuple", pos);
            result = new ErlTuple(items, false);
            break;

              case '[':
            if (fmt[pos] == ']')
            {
              result = new ErlList();
              pos++;
              break;
            }
            else if (State.Ok == pList(fmt, ref pos, ref items, ref argc, args))
            {
              result = new ErlList(items, false);
              break;
            }
            throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "list", pos);

              case '<':
            if (pos < fmt.Length - 1 && fmt[pos] == '<')
            {
              var i = ++pos;
              var str = fmt[i] == '"';
              if (str) pos++;
              for (; i < fmt.Length && fmt[i - 1] != '>' && fmt[i] != '>'; ++i);
              if (i == fmt.Length)
                break;
              var end   = ++i - (str ? 3 : 2);
              var len   = end - pos + 1;
              byte[] bytes;
              if (str)
              {
                var cnt = Encoding.UTF8.GetByteCount(fmt.ToCharArray(), pos, len);
                bytes = new byte[cnt];
                Encoding.UTF8.GetBytes(fmt, pos, len, bytes, 0);
              }
              else
              {
                var beg = pos - 2;
                bytes   = fmt.Substring(pos, len)
                             .Split(new char[] {',', ' '},
                                    StringSplitOptions.RemoveEmptyEntries)
                             .Select(s =>
                             {
                               var n = int.Parse(s);
                               if (n < 0 || n > 255)
                                 throw new ErlException
                                  ("Invalid binary in format string: {0}".Args(fmt.Substring(beg, len+4)));
                               return (byte)n;
                             })
                             .ToArray();
              }
              result = new ErlBinary(bytes, 0, bytes.Length);
              pos = i+1;
            }
            break;
              case '$': /* char-value? */
            result = new ErlByte(Convert.ToByte(fmt[pos++]));
            break;

              case '~':
            if (State.Ok != pFormat(fmt, ref pos, ref items, ref argc, args))
              throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "term", pos);
            result = items[0];
            break;

              default:
            char c = fmt[--pos];
            if (char.IsLower(c))
            {         /* atom  ? */
              string s = pAtom(fmt, ref pos);
              result = createAtom(s);
            }
            else if (char.IsUpper(c) || c == '_')
            {
              result = pVariable(fmt, ref pos);
            }
            else if (char.IsDigit(c) || c == '-')
            {    /* integer/float ? */
              string s = pDigit(fmt, ref pos);
              if (s.IndexOf('.') < 0)
                result = new ErlLong(long.Parse(s, CultureInfo.InvariantCulture));
              else
                result = new ErlDouble(double.Parse(s, CultureInfo.InvariantCulture));
            }
            else if (c == '"')
            {      /* string ? */
              string s = pString(fmt, ref pos);
              result = new ErlString(s);
            }
            else if (c == '\'')
            {     /* quoted atom ? */
              string s = pQuotedAtom(fmt, ref pos);
              result = createAtom(s);
            }
            break;
            }
              }

              if (result == null)
            throw new ErlException(StringConsts.ERL_INVALID_VALUE_ERROR.Args(fmt));

              return result;
        }
Example #15
0
        /// <summary>
        /// Maps ErlRow to CLR row supplied by schema, either Dynamic or TypedRow
        /// </summary>
        public Row ErlTupleToRow(string schemaName, ErlTuple tuple, Schema schema)
        {
            var singleKey = schema.ExtraData[SCHEMA_KEY_COUNT].AsInt(0) < 2;

            var row = Row.MakeRow(schema, schema.TypedRowType);

            var i = -1;

            foreach (var elm in enumErlResponseTuple(tuple, singleKey))
            {
                i++;
                if (i == 0)
                {
                    var thisname = tuple[0].ValueAsString;
                    if (!schemaName.EqualsOrdSenseCase(thisname))
                    {
                        throw new ErlDataAccessException(StringConsts.ERL_DS_CRUD_RESPONSE_SCHEMA_MISMATCH_ERROR.Args(thisname, schemaName));
                    }
                    continue;
                }

                //map fields now
                if (i - 1 >= schema.FieldCount)
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_CRUD_RESPONSE_SCHEMA_FLD_COUNT_MISMATCH_ERROR.Args(schemaName, schema.Name));
                }
                var fdef = schema[i - 1];
                var atr  = fdef[m_Store.TargetName];

                var erlType = atr.BackendType;
                if (erlType.IsNullOrWhiteSpace())
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_INTERNAL_MAPPING_ERROR + "fielddef('{0}') has no backend type".Args(fdef.Name));
                }


                if (elm.IsNull())
                {
                    row.SetFieldValue(fdef, null);
                    continue;
                }

                Tuple <Type, Func <IErlObject, object> > mapping;
                if (ERL_TO_CLR_TYPEMAP.TryGetValue(erlType, out mapping))
                {
                    object clrValue = null;

                    try
                    {
                        clrValue = mapping.Item2(elm);
                    }
                    catch (Exception error)
                    {
                        App.Log.Write(new Log.Message
                        {
                            Type      = Log.MessageType.TraceErl,
                            Topic     = CoreConsts.ERLANG_TOPIC,
                            From      = "SchemaMap.ErlTupleToRow({0})".Args(schemaName),
                            Text      = "Error converting element '{0}'->'{1}': {2}".Args(erlType, elm.GetType(), error.ToMessageWithType()),
                            Exception = error
                        });
                        throw;
                    }
                    row.SetFieldValue(fdef, clrValue);
                }
                else
                {
                    throw new ErlDataAccessException(StringConsts.ERL_DS_INTERNAL_MAPPING_ERROR + "erltype'{0}' not matched in the dict".Args(erlType));
                }
            }

            return(row);
        }
Example #16
0
        public void ErlTermSerializeTest()
        {
            {
                var b  = new byte[] { 131, 100, 0, 3, 97, 98, 99 };
                var t  = new ErlAtom("abc");
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 109, 0, 0, 0, 3, 1, 2, 3 };
                var t  = new ErlBinary(new byte[] { 1, 2, 3 });
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b1  = new byte[] { 131, 100, 0, 4, 116, 114, 117, 101 };
                var t1  = new ErlBoolean(true);
                var os1 = new ErlOutputStream(t1);
                Assert.AreEqual(b1, os1.GetBuffer().TakeWhile((_, i) => i < b1.Length).ToArray());
                var es1 = new ErlInputStream(b1);
                Assert.AreEqual(t1, es1.Read());

                var b2  = new byte[] { 131, 100, 0, 5, 102, 97, 108, 115, 101 };
                var t2  = new ErlBoolean(false);
                var os2 = new ErlOutputStream(t2);
                Assert.AreEqual(b2, os2.GetBuffer().TakeWhile((_, i) => i < b2.Length).ToArray());
                var es2 = new ErlInputStream(b2);
                Assert.AreEqual(t2, es2.Read());
            }
            {
                var b  = new byte[] { 131, 97, 127 };
                var t  = new ErlByte(127);
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 70, 64, 36, 62, 249, 219, 34, 208, 229 };
                var t  = new ErlDouble(10.123);
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b = new byte[] { 131, 108, 0, 0, 0, 3, 97, 1, 70, 64, 36, 61, 112, 163, 215, 10, 61, 108, 0, 0, 0, 2,
                                     100, 0, 4, 116, 114, 117, 101, 107, 0, 1, 97, 106, 106 };
                var t  = new ErlList(1, 10.12, new ErlList(true, "a"));
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b1  = new byte[] { 131, 98, 255, 255, 255, 251 };
                var t1  = new ErlLong(-5);
                var os1 = new ErlOutputStream(t1);
                Assert.AreEqual(b1, os1.GetBuffer().TakeWhile((_, i) => i < b1.Length).ToArray());
                var es1 = new ErlInputStream(b1);
                Assert.AreEqual(t1, es1.Read());

                var b2  = new byte[] { 131, 97, 5 };
                var t2  = new ErlLong(5);
                var os2 = new ErlOutputStream(t2);
                Assert.AreEqual(b2, os2.GetBuffer().TakeWhile((_, i) => i < b2.Length).ToArray());
                var es2 = new ErlInputStream(b2);
                Assert.AreEqual(t2, es2.Read());

                var b3  = new byte[] { 131, 98, 0, 16, 0, 0 };
                var t3  = new ErlLong(1024 * 1024);
                var os3 = new ErlOutputStream(t3);
                Assert.AreEqual(b3, os3.GetBuffer().TakeWhile((_, i) => i < b3.Length).ToArray());
                var es3 = new ErlInputStream(b3);
                Assert.AreEqual(t3, es3.Read());

                var b4  = new byte[] { 131, 110, 6, 0, 0, 0, 0, 0, 0, 4 };
                var t4  = new ErlLong(1024L * 1024 * 1024 * 1024 * 4);
                var os4 = new ErlOutputStream(t4);
                Assert.AreEqual(b4, os4.GetBuffer().TakeWhile((_, i) => i < b4.Length).ToArray());
                var es4 = new ErlInputStream(b4);
                Assert.AreEqual(t4, es4.Read());

                var b5  = new byte[] { 131, 110, 8, 1, 0, 0, 0, 0, 0, 0, 0, 128 };
                var t5  = new ErlLong(1L << 63);
                var os5 = new ErlOutputStream(t5);
                Assert.AreEqual(b5, os5.GetBuffer().TakeWhile((_, i) => i < b5.Length).ToArray());
                var es5 = new ErlInputStream(b5);
                Assert.AreEqual(t5, es5.Read());

                var b6  = new byte[] { 131, 110, 8, 1, 0, 0, 0, 0, 0, 0, 0, 128 };
                var t6  = new ErlLong(-1L << 63);
                var os6 = new ErlOutputStream(t6);
                Assert.AreEqual(b6, os6.GetBuffer().TakeWhile((_, i) => i < b6.Length).ToArray());
                var es6 = new ErlInputStream(b6);
                Assert.AreEqual(t6, es6.Read());

                var b7  = new byte[] { 131, 110, 8, 0, 255, 255, 255, 255, 255, 255, 255, 255 };
                var es7 = new ErlInputStream(b7);
                var t7  = new ErlLong(-1);
                Assert.AreEqual(t7, es7.Read());
                var bi7 = new byte[] { 131, 98, 255, 255, 255, 255 };
                var os7 = new ErlOutputStream(t7);
                Assert.AreEqual(bi7, os7.GetBuffer().TakeWhile((_, i) => i < bi7.Length).ToArray());
            }
            {
                var b  = new byte[] { 131, 103, 100, 0, 7, 98, 64, 112, 105, 112, 105, 116, 0, 0, 0, 38, 0, 0, 0, 0, 1 };
                var t  = new ErlPid("b@pipit", 38, 0, 1);
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 102, 100, 0, 7, 98, 64, 112, 105, 112, 105, 116, 0, 0, 0, 38, 1 };
                var t  = new ErlPort("b@pipit", 38, 1);
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 114, 0, 3, 100, 0, 7, 98, 64, 112, 105, 112, 105, 116, 1, 0, 0, 0, 181, 0, 0, 0, 0, 0, 0, 0, 0 };
                var t  = new ErlRef("b@pipit", 181, 0, 0, 1);
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 107, 0, 3, 115, 116, 114 };
                var t  = new ErlString("str");
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
            {
                var b  = new byte[] { 131, 104, 3, 97, 1, 100, 0, 1, 97, 104, 2, 97, 10, 70, 63, 241, 247, 206, 217, 22, 135, 43 };
                var t  = new ErlTuple(1, new ErlAtom("a"), new ErlTuple(10, 1.123));
                var os = new ErlOutputStream(t);
                Assert.AreEqual(b, os.GetBuffer().TakeWhile((_, i) => i < b.Length).ToArray());
                var es = new ErlInputStream(b);
                Assert.AreEqual(t, es.Read());
            }
        }
Example #17
0
        /// <summary>
        /// Converts CLR row data into ErlTuple
        /// </summary>
        public ErlTuple RowToErlTuple(Row row, bool keysOnly = false)
        {
            var result = new ErlTuple();

            result.Add(new ErlAtom(row.Schema.Name));

            var keys = new List <IErlObject>();

            foreach (var def in row.Schema)
            {
                var atr = def[m_Store.TargetName];

                if (keysOnly && !atr.Key)
                {
                    break;
                }

                if (keys != null && !atr.Key)
                {
                    if (keys.Count > 1)
                    {
                        result.Add(new ErlTuple(keys, false));
                    }
                    else
                    {
                        foreach (var key in keys)
                        {
                            result.Add(key);
                        }
                    }
                    keys = null;
                }


                IErlObject erlValue = ErlAtom.Undefined;

                var clrValue = row.GetFieldValue(def);
                if (clrValue != null)
                {
                    Func <object, IErlObject> fconv;
                    if (!CLR_TO_ERL_TYPEMAP.TryGetValue(atr.BackendType, out fconv))
                    {
                        throw new ErlDataAccessException(StringConsts.ERL_DS_INTERNAL_MAPPING_ERROR + "erltype'{0}' not matched in the dict".Args(atr.BackendType));
                    }

                    erlValue = fconv(clrValue);
                }

                if (keys != null)
                {
                    keys.Add(erlValue);
                }
                else
                {
                    result.Add(erlValue);
                }
            }

            if (keys != null)
            {
                if (keys.Count > 1)
                {
                    result.Add(new ErlTuple(keys, false));
                }
                else
                {
                    foreach (var key in keys)
                    {
                        result.Add(key);
                    }
                }
            }

            return(result);
        }
Example #18
0
        /// <summary>
        /// Compile a string fmt into an Erlang term
        /// </summary>
        internal static IErlObject Parse(
            string fmt, ref int pos, ref int argc, params object[] args)
        {
            var        items  = new List <IErlObject>();
            IErlObject result = null;

            pos = skipWSAndComments(fmt, pos);

            if (pos < fmt.Length)
            {
                switch (fmt[pos++])
                {
                case '{':
                    if (State.Ok != pTuple(fmt, ref pos, ref items, ref argc, args))
                    {
                        throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "tuple", pos);
                    }
                    result = new ErlTuple(items, false);
                    break;

                case '[':
                    if (fmt[pos] == ']')
                    {
                        result = new ErlList();
                        pos++;
                        break;
                    }
                    else if (State.Ok == pList(fmt, ref pos, ref items, ref argc, args))
                    {
                        result = new ErlList(items, false);
                        break;
                    }
                    throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "list", pos);

                case '<':
                    if (pos < fmt.Length - 1 && fmt[pos] == '<')
                    {
                        var i   = ++pos;
                        var str = fmt[i] == '"';
                        if (str)
                        {
                            pos++;
                        }
                        for (; i < fmt.Length && fmt[i - 1] != '>' && fmt[i] != '>'; ++i)
                        {
                            ;
                        }
                        if (i == fmt.Length)
                        {
                            break;
                        }
                        var    end = ++i - (str ? 3 : 2);
                        var    len = end - pos + 1;
                        byte[] bytes;
                        if (str)
                        {
                            var cnt = Encoding.UTF8.GetByteCount(fmt.ToCharArray(), pos, len);
                            bytes = new byte[cnt];
                            Encoding.UTF8.GetBytes(fmt, pos, len, bytes, 0);
                        }
                        else
                        {
                            var beg = pos - 2;
                            bytes = fmt.Substring(pos, len)
                                    .Split(new char[] { ',', ' ' },
                                           StringSplitOptions.RemoveEmptyEntries)
                                    .Select(s =>
                            {
                                var n = int.Parse(s);
                                if (n < 0 || n > 255)
                                {
                                    throw new ErlException
                                        ("Invalid binary in format string: {0}".Args(fmt.Substring(beg, len + 4)));
                                }
                                return((byte)n);
                            })
                                    .ToArray();
                        }
                        result = new ErlBinary(bytes, 0, bytes.Length);
                        pos    = i + 1;
                    }
                    break;

                case '$': /* char-value? */
                    result = new ErlByte(Convert.ToByte(fmt[pos++]));
                    break;

                case '~':
                    if (State.Ok != pFormat(fmt, ref pos, ref items, ref argc, args))
                    {
                        throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "term", pos);
                    }
                    result = items[0];
                    break;

                default:
                    char c = fmt[--pos];
                    if (char.IsLower(c))
                    { /* atom  ? */
                        string s = pAtom(fmt, ref pos);
                        result = createAtom(s);
                    }
                    else if (char.IsUpper(c) || c == '_')
                    {
                        result = pVariable(fmt, ref pos);
                    }
                    else if (char.IsDigit(c) || c == '-')
                    { /* integer/float ? */
                        string s = pDigit(fmt, ref pos);
                        if (s.IndexOf('.') < 0)
                        {
                            result = new ErlLong(long.Parse(s, CultureInfo.InvariantCulture));
                        }
                        else
                        {
                            result = new ErlDouble(double.Parse(s, CultureInfo.InvariantCulture));
                        }
                    }
                    else if (c == '"')
                    { /* string ? */
                        string s = pString(fmt, ref pos);
                        result = new ErlString(s);
                    }
                    else if (c == '\'')
                    { /* quoted atom ? */
                        string s = pQuotedAtom(fmt, ref pos);
                        result = createAtom(s);
                    }
                    break;
                }
            }

            if (result == null)
            {
                throw new ErlException(StringConsts.ERL_INVALID_VALUE_ERROR.Args(fmt));
            }

            return(result);
        }
Example #19
0
        static void Main(string[] args)
        {
            //here we handle password requests
            ErlTransportPasswordSource.PasswordRequired += (ps) =>
            {
                Console.Write("Username: {0}\nPassword: "******"{0} ({1}): {2}", t, d, text);

                n.Start();

                var cfg        = App.ConfigRoot.NavigateSection("/erlang");
                var remoteName = cfg.Children.Select(nd => nd.Name == "node" ? nd.Value : string.Empty)
                                 .FirstOrDefault(s => s.Contains("@"));

                Console.WriteLine("\n\nExecute the following code on remote node {0}:", remoteName);
                Console.WriteLine("1> F = fun F() -> receive {From, Msg} -> From ! Msg, F() end end.");
                Console.WriteLine("2> spawn_link(fun() -> register(me, self()), F() end).\n");
                Console.WriteLine("Press any key when ready...");

                Console.ReadKey();

                var m          = n.CreateMbox("test");
                var a          = new ErlAtom("hello");
                var msg        = new ErlTuple(m.Self, a);
                var remoteNode = new ErlAtom(remoteName);

                DateTime empty = new DateTime(2000, 1, 1, 0, 0, 0);
                DateTime start = empty;
                long     count = 0;
                long     msgs  = 30000;

                do
                {
                    var res = n.Send(m.Self, remoteNode, "me", msg);
                    if (!res)
                    {
                        Console.WriteLine("Can not send message");
                        break;
                    }

                    if (start == empty)
                    {
                        start = DateTime.UtcNow;
                    }

                    var got = m.Receive(5000);

                    if (!got.Equals((IErlObject)a))
                    {
                        Console.WriteLine("Got wrong result! Expected: {0}, Got: {1}", a, got);
                        count = -1;
                        break;
                    }

                    count++;

                    if ((count % 10000) == 0)
                    {
                        Console.WriteLine("Processed {0} messages", count);
                    }
                    //Console.ReadLine();
                } while (count < msgs);

                var end  = DateTime.UtcNow;
                var diff = (end - start);

                if (count > 0)
                {
                    Console.WriteLine("Processed {0} messages. Speed: {1:F2}msgs/s, Latency: {2}us",
                                      msgs, msgs / diff.TotalSeconds, 1000.0 * diff.TotalMilliseconds / msgs);
                }
            }

            if (Debugger.IsAttached)
            {
                Console.ReadKey();
            }
        }