private static Expression GetSizeExpression(Type type, Expression memory, Expression access)
            {
                var specificSizeExpression = GetSpecificSizeExpression(type, memory, access);

                if (specificSizeExpression != null)
                {
                    return(specificSizeExpression);
                }

                if (type.IsArray)
                {
                    return(Expression.Call(memory, "GetSizeOfSealedInternal", new Type[] { type }, access));
                }

                if (type.IsSealed)
                {
                    if (type.IsValueType)
                    {
                        var fields = TypeFields.GetFields(type);
                        var all    = GetReferenceSizes(fields, access, memory).Aggregate((Expression)Expression.Constant(0L), (x, y) => Expression.Add(x, y));

                        return(Expression.Add(all, Expression.Constant(GetSizeOfType(type))));
                    }

                    return(Expression.Call(memory, "GetSizeOfSealedInternal", new Type[] { type }, access));
                }
                else
                {
                    return(Expression.Call(memory, "GetSizeOfInternal", Array.Empty <Type>(), access));
                }
            }
Exemple #2
0
        public void SetFormat(string fieldName, Type fieldType, string format, int width)
        {
            if (!string.IsNullOrWhiteSpace(fieldName))
            {
                if (!string.IsNullOrWhiteSpace(format))
                {
                    if (!FormatFields.ContainsKey(fieldName))
                    {
                        FormatFields.Add(fieldName, format);
                    }
                }

                if (fieldType != null)
                {
                    if (!TypeFields.ContainsKey(fieldName))
                    {
                        TypeFields.Add(fieldName, fieldType);
                    }
                }

                if (width > 0)
                {
                    if (!SizeFields.ContainsKey(fieldName))
                    {
                        SizeFields.Add(fieldName, width);
                    }
                }
            }
        }
        internal static bool IsBlittable(Type elementType)
        {
            return(_isBlittableCache.GetOrAdd(elementType, _ =>
            {
                if (!elementType.IsValueType)
                {
                    return false;
                }

                if (!TypeFields.IsPrimitive(elementType))
                {
                    return false;
                }

                try
                {
                    WriteArrayOfValuesMethod1.MakeGenericMethod(elementType);
                    return true;
                }
                catch
                {
                    return false;
                }
            }));
        }
            private static IEnumerable <Expression> GetReferenceSizes(List <FieldInfo> fields,
                                                                      Expression source,
                                                                      Expression memory)
            {
                foreach (var field in fields)
                {
                    var fieldType = field.FieldType;
                    if (fieldType.IsPrimitive || fieldType.IsPointer)
                    {
                        continue;
                    }

                    var subSource = Expression.MakeMemberAccess(source, field);

                    if (fieldType.IsValueType && !(fieldType == typeof(ValueTask) || (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(ValueTask <>))))
                    {
                        var fieldTypeFields = TypeFields.GetFields(fieldType);
                        var subSizes        = GetReferenceSizes(fieldTypeFields, subSource, memory);
                        foreach (var subResult in subSizes)
                        {
                            yield return(subResult);
                        }
                    }
                    else
                    {
                        yield return(GetSizeExpression(fieldType, memory, subSource));
                    }
                }
            }
        public IFieldBuilder DefineField(string name, IType fieldType, FieldAttributes attributes)
        {
            var builder = new AsmFieldBuilder(this, fieldType, attributes, name);

            TypeFields.Add(builder);
            return(builder);
        }
        internal bool IsTypeSerializable(Type type)
        {
            if (type.IsGenericType && !type.IsGenericTypeDefinition)
            {
                type = type.GetGenericTypeDefinition();
                if (_autoWhitelistedTypes.Contains(type))
                {
                    return(true);
                }
            }

            if (type == typeof(FieldInfoModifier.TestReadonly))
            {
                return(true);
            }

            if (type.IsArray)
            {
                return(true);
            }

            if (typeof(Delegate).IsAssignableFrom(type))
            {
                return(true);
            }

            if (typeof(Type).IsAssignableFrom(type))
            {
                return(true);
            }

            if (type.GetCustomAttribute(typeof(CompilerGeneratedAttribute)) != null)
            {
                return(true);
            }

            if (TypeFields.IsPrimitive(type))
            {
                return(true);
            }

            if (IsSpecialCoreType(type))
            {
                return(true);
            }

            if (_autoWhitelistedTypes.Contains(type))
            {
                return(true);
            }

            var declaringTypeIsSerializeable = type.DeclaringType != null && IsTypeSerializable(type.DeclaringType);

            return(declaringTypeIsSerializeable ||
                   WhitelistedTypes.Contains(type) ||
                   WhitelistFuncs.Any(x => x(type)));
        }
        private static Expression?WriteArray(Type type,
                                             ParameterExpression stream,
                                             ParameterExpression output,
                                             Expression actualSource,
                                             ImmutableSettings settings,
                                             ImmutableHashSet <Type> visitedTypes,
                                             int depth)
        {
            if (type.IsArray)
            {
                var elementType = type.GetElementType() !;
                var dimensions  = type.GetArrayRank();

                var(elementSize, isRef) = TypeFields.GetSizeForType(elementType);

                var lengths = new List <ParameterExpression>();
                for (int i = 0; i < dimensions; ++i)
                {
                    lengths.Add(Expression.Variable(typeof(int), $"length{i}"));
                }

                var statements = new List <Expression>();

                statements.Add(ReserveConstantSize(stream, 4 * dimensions));
                statements.AddRange(lengths.Select((x, i) =>
                                                   Expression.Assign(x, Expression.Call(actualSource, "GetLength", Array.Empty <Type>(), Expression.Constant(i)))));
                statements.AddRange(lengths.Select(x =>
                                                   Expression.Call(stream, BinaryStreamMethods <TStream> .GenericMethods <int> .WriteValueMethodInfo, x)));

                // don't write anything else if lengths are zero
                var skipLabel = Expression.Label("skipWrite");
                statements.Add(
                    Expression.IfThen(
                        Expression.Equal(Expression.Constant(0), lengths.Aggregate((Expression)Expression.Empty(), (a, b) => a.NodeType == ExpressionType.Default ? (Expression)b : Expression.Or(a, b))),
                        Expression.Goto(skipLabel)
                        )
                    );

                if (IsBlittable(elementType) && dimensions < 3)
                {
                    statements.Add(WriteArrayOfBlittableValues(output, actualSource, stream, dimensions, elementType, elementSize));
                }
                else
                {
                    statements.Add(WriteArrayGeneral(output, actualSource, stream, dimensions, lengths, elementType, elementSize, settings, visitedTypes, depth));
                }

                statements.Add(Expression.Label(skipLabel));

                return(Expression.Block(lengths, statements));
            }

            return(null);
        }
Exemple #8
0
            private void ReadEmbedded(UnityBinaryReader reader, int version, int typeVersion)
            {
                int fieldCount        = reader.ReadInt32();
                int stringTableLength = reader.ReadInt32();

                TypeFields.Capacity = fieldCount;
                TypeFields.Clear();

                for (int i = 0; i < fieldCount; i++)
                {
                    var field = new Field(reader);
                    TypeFields.Add(field);
                }

                ReadStringTable(reader, stringTableLength);
            }
        public void Can_use_TypedFields_accessor()
        {
            var runtimeType = typeof(MyType);
            var typeProps   = TypeFields.Get(runtimeType); //Equivalent to:
            //  typeProps = TypeFields<MyType>.Instance;

            var instance = runtimeType.CreateInstance();

            var propAccessor = typeProps.GetAccessor("LongField");

            propAccessor.PublicSetter(instance, 1L);
            Assert.That(propAccessor.PublicGetter(instance), Is.EqualTo(1));

            typeProps.GetPublicSetter("StringField")(instance, "foo");
            var value = typeProps.GetPublicGetter("StringField")(instance);

            Assert.That(value, Is.EqualTo("foo"));
        }
Exemple #10
0
        private static object PropValue(object targetValue, Type targetType, string name)
        {
            var memberFn = TypeProperties.Get(targetType).GetPublicGetter(name)
                           ?? TypeFields.Get(targetType).GetPublicGetter(name);

            if (memberFn != null)
            {
                return(memberFn(targetValue));
            }

            var indexerMethod = targetType.GetInstanceMethod("get_Item");

            if (indexerMethod != null)
            {
                var fn  = indexerMethod.GetInvoker();
                var ret = fn(targetValue, name);
                return(ret ?? JsNull.Value);
            }

            throw new ArgumentException($"'{targetType.Name}' does not have a '{name}' property or field");
        }
Exemple #11
0
            private static bool HasNoReferences(Type elementType)
            {
                if (!elementType.IsSealed || elementType.IsInterface || elementType.IsAbstract)
                {
                    return(false);
                }

                if (elementType == typeof(string))
                {
                    return(false);
                }

                if (elementType.IsArray)
                {
                    return(false);
                }

                var fields = TypeFields.GetFields(elementType);

                return(fields.All(x => x.FieldType.IsPrimitive || x.FieldType.IsValueType && HasNoReferences(x.FieldType)));
            }
Exemple #12
0
        public static T ConvertToValueTuple <T>(this IDataReader reader, object[] values, IOrmLiteDialectProvider dialectProvider)
        {
            var row        = typeof(T).CreateInstance();
            var typeFields = TypeFields.Get(typeof(T));

            values = reader.PopulateValues(values, dialectProvider);

            for (var i = 0; i < reader.FieldCount; i++)
            {
                var itemName = $"Item{(i + 1)}";
                var field    = typeFields.GetAccessor(itemName);
                if (field == null)
                {
                    break;
                }

                var dbValue = values != null
                    ? values[i]
                    : reader.GetValue(i);

                if (dbValue == null)
                {
                    continue;
                }

                var fieldType = field.FieldInfo.FieldType;
                if (dbValue.GetType() == fieldType)
                {
                    field.PublicSetterRef(ref row, dbValue);
                }
                else
                {
                    var converter  = dialectProvider.GetConverter(fieldType);
                    var fieldValue = converter.FromDbValue(fieldType, dbValue);
                    field.PublicSetterRef(ref row, fieldValue);
                }
            }

            return((T)row);
        }
Exemple #13
0
        private static object PropValue(object targetValue, Type targetType, string name)
        {
            var memberFn = TypeProperties.Get(targetType).GetPublicGetter(name)
                           ?? TypeFields.Get(targetType).GetPublicGetter(name);

            if (memberFn != null)
            {
                return(memberFn(targetValue));
            }

            var methods       = targetType.GetInstanceMethods();
            var indexerMethod =
                methods.FirstOrDefault(x => x.Name == "get_Item" && x.GetParameters().Any(p => p.ParameterType == typeof(string))) ??
                methods.FirstOrDefault(x => x.Name == "get_Item" && x.GetParameters().Any(p => p.ParameterType != typeof(string)));

            if (indexerMethod != null)
            {
                var fn  = indexerMethod.GetInvoker();
                var ret = fn(targetValue, name);
                return(ret);
            }

            throw new ArgumentException($"'{targetType.Name}' does not have a '{name}' property or field");
        }
        private object GetValue(object targetValue, TemplateScopeContext scope)
        {
            if (targetValue == null || targetValue == JsNull.Value)
            {
                return(JsNull.Value);
            }
            var targetType = targetValue.GetType();

            try
            {
                object propValue(string name)
                {
                    var memberFn = TypeProperties.Get(targetType).GetPublicGetter(name)
                                   ?? TypeFields.Get(targetType).GetPublicGetter(name);

                    if (memberFn != null)
                    {
                        return(memberFn(targetValue));
                    }

                    var indexerMethod = targetType.GetInstanceMethod("get_Item");

                    if (indexerMethod != null)
                    {
                        var fn  = indexerMethod.GetInvoker();
                        var ret = fn(targetValue, name);
                        return(ret ?? JsNull.Value);
                    }

                    throw new ArgumentException($"'{targetType.Name}' does not have a '{name}' property or field");
                }

                if (!Computed)
                {
                    if (Property is JsIdentifier identifier)
                    {
                        var ret = propValue(identifier.NameString);

                        // Don't emit member expression on null KeyValuePair
                        if (ret == null && targetType.Name == "KeyValuePair`2")
                        {
                            return(JsNull.Value);
                        }

                        return(ret);
                    }
                }
                else
                {
                    var indexValue = Property.Evaluate(scope);
                    if (indexValue == null)
                    {
                        return(JsNull.Value);
                    }

                    if (targetType.IsArray)
                    {
                        var array = (Array)targetValue;
                        if (indexValue is long l)
                        {
                            return(array.GetValue(l));
                        }
                        var intValue = indexValue.ConvertTo <int>();
                        return(array.GetValue(intValue));
                    }
                    if (targetValue is IDictionary dict)
                    {
                        var ret = dict[indexValue];
                        return(ret ?? JsNull.Value);
                    }
                    if (indexValue is string propName)
                    {
                        return(propValue(propName));
                    }
                    if (targetValue is IList list)
                    {
                        var intValue = indexValue.ConvertTo <int>();
                        return(list[intValue]);
                    }
                    if (targetValue is IEnumerable e)
                    {
                        var intValue = indexValue.ConvertTo <int>();
                        var i        = 0;
                        foreach (var item in e)
                        {
                            if (i++ == intValue)
                            {
                                return(item);
                            }
                        }
                        return(null);
                    }
                    if (DynamicNumber.IsNumber(indexValue.GetType()))
                    {
                        var indexerMethod = targetType.GetInstanceMethod("get_Item");
                        if (indexerMethod != null)
                        {
                            var fn  = indexerMethod.GetInvoker();
                            var ret = fn(targetValue, indexValue);
                            return(ret ?? JsNull.Value);
                        }
                    }
                }
            }
            catch (KeyNotFoundException)
            {
                return(JsNull.Value);
            }
            catch (Exception ex)
            {
                var exResult = scope.PageResult.Format.OnExpressionException(scope.PageResult, ex);
                if (exResult != null)
                {
                    return(exResult);
                }

                var expr = ToRawString();
                throw new BindingExpressionException($"Could not evaluate expression '{expr}'", null, expr, ex);
            }

            throw new NotSupportedException($"'{targetValue.GetType()}' does not support access by '{Property}'");
        }
Exemple #15
0
            private static Delegate GenerateMethodImpl(Type type, bool isVirtual)
            {
                var source = Expression.Parameter(isVirtual ? typeof(object) : type, "obj");
                var memory = Expression.Parameter(typeof(Memory), "memory");

                var statements     = new List <Expression>();
                var localVariables = new List <ParameterExpression>();

                var castedSource = source;

                if (isVirtual)
                {
                    castedSource = Expression.Variable(type);
                    localVariables.Add(castedSource);
                    statements.Add(Expression.Assign(castedSource, Expression.Convert(source, type)));
                }

                var result = Expression.Variable(typeof(long), "result");

                localVariables.Add(result);

                statements.Add(Expression.Assign(result, Expression.Constant(0L)));

                var specificSizeExpression = GetSpecificSizeExpression(type, memory, castedSource);

                if (specificSizeExpression != null)
                {
                    statements.Add(Expression.AddAssign(result, specificSizeExpression));
                }
                else
                {
                    if (type == typeof(string))
                    {
                        statements.Add(Expression.AddAssign(result, Expression.Condition(
                                                                Expression.ReferenceEqual(castedSource, Expression.Constant(null)),
                                                                Expression.Constant(0L),
                                                                Expression.Condition(
                                                                    Expression.Equal(Expression.Property(castedSource, "Length"), Expression.Constant(0)),
                                                                    Expression.Constant(0L),
                                                                    Expression.Convert(
                                                                        Expression.And(Expression.Constant(0b11111100),
                                                                                       Expression.Add(Expression.Constant(IntPtr.Size * 4), Expression.Multiply(Expression.Constant(2), Expression.Property(castedSource, "Length")))
                                                                                       ),
                                                                        typeof(long))
                                                                    )
                                                                )));
                    }
                    else if (type.IsArray)
                    {
                        statements.Add(Expression.AddAssign(result, Expression.Constant((long)IntPtr.Size * 3)));
                        var elementType = type.GetElementType();
                        var dimensions  = type.GetArrayRank();
                        var lengths     = new List <ParameterExpression>();
                        for (int i = 0; i < dimensions; ++i)
                        {
                            lengths.Add(Expression.Variable(typeof(int)));
                        }

                        var loopExpressions = new List <Expression>();
                        loopExpressions.AddRange(lengths.Select((x, i) =>
                                                                Expression.Assign(x, Expression.Call(castedSource, "GetLength", Array.Empty <Type>(), Expression.Constant(i)))));

                        if (HasNoReferences(elementType))
                        {
                            loopExpressions.Add(
                                Expression.AddAssign(result,
                                                     lengths.Select(x => Expression.Convert(x, typeof(long))).Aggregate((Expression)Expression.Constant(GetSizeOfType(elementType)), (x, y) => Expression.Multiply(x, y))));
                            statements.Add(Expression.Block(lengths, loopExpressions));
                        }
                        else
                        {
                            loopExpressions.Add(Expression.AddAssign(result,
                                                                     lengths.Select(x => Expression.Convert(x, typeof(long))).Aggregate((Expression)Expression.Constant((long)IntPtr.Size), (x, y) => Expression.Multiply(x, y))));

                            var indices        = new List <ParameterExpression>();
                            var breakLabels    = new List <LabelTarget>();
                            var continueLabels = new List <LabelTarget>();

                            for (int i = 0; i < dimensions; ++i)
                            {
                                indices.Add(Expression.Variable(typeof(int)));
                                breakLabels.Add(Expression.Label());
                                continueLabels.Add(Expression.Label());
                            }

                            var accessExpression = dimensions > 1
                                ? (Expression)Expression.ArrayIndex(castedSource, indices)
                                : Expression.ArrayIndex(castedSource, indices[0]);

                            Expression getSize = Expression.AddAssign(result, GetSizeExpression(elementType, memory, accessExpression));

                            var loop = getSize;

                            for (int i = 0; i < dimensions; ++i)
                            {
                                loop =
                                    Expression.Block(
                                        Expression.Assign(indices[i], Expression.Constant(0)),
                                        Expression.Loop(Expression.IfThenElse(
                                                            Expression.GreaterThanOrEqual(indices[i], lengths[i]),
                                                            Expression.Break(breakLabels[i]),
                                                            Expression.Block(loop, Expression.Label(continueLabels[i]), Expression.Assign(indices[i], Expression.Increment(indices[i])))
                                                            ), breakLabels[i])
                                        );
                            }

                            loopExpressions.Add(Expression.Block(indices, loop));

                            statements.Add(Expression.Block(lengths, loopExpressions));
                        }
                    }
                    else
                    {
                        statements.Add(Expression.AddAssign(result, Expression.Constant(GetSizeOfType(type))));
                        var fields = TypeFields.GetFields(type);
                        statements.AddRange(GetReferenceSizes(fields, castedSource, memory).Select(x => Expression.AddAssign(result, x)));
                    }

                    statements.Add(result);
                }

                var lambda = Expression.Lambda(Expression.Block(localVariables, statements), $"Apex.Runtime.Memory_SizeOf_{type.FullName}", new[] { source, memory }).Compile();

                return(lambda);
            }