void InitMethodTable(Dictionary <Type, List <MethodInfo> > table, Type attribute, bool byRef)
 {
     foreach (MethodInfo info in
              this.GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
     {
         if (MarshalingDescriptor.HasAttribute(info, attribute))
         {
             ParameterInfo[] ps = info.GetParameters();
             if (ps.Length == 1)
             {
                 Type pt = ps[0].ParameterType;
                 if (!byRef || byRef && pt.IsByRef && !ps[0].IsOut)
                 {
                     if (byRef)
                     {
                         pt = pt.GetElementType();
                     }
                     List <MethodInfo> ms;
                     if (!table.TryGetValue(pt, out ms))
                     {
                         table[pt] = ms = new List <MethodInfo>();
                     }
                     ms.Add(info);
                 }
             }
         }
     }
 }
        private void CheckPossibleValueInUnion(object value, ICustomAttributeProvider provider)
        {
            string switchExpr;

            if (provider == null || !MarshalingDescriptor.TryGetAttribute <string>(
                    provider, typeof(SwitchAttribute), "expr",
                    out switchExpr))
            {
                throw new InvalidOperationException(String.Format(
                                                        CultureInfo.InvariantCulture,
                                                        "cannot find switch attribute for union '{0}'",
                                                        value.GetType().Name));
            }

            Type type          = value.GetType();
            var  fieldsToCheck = new List <FieldInfo>();
            var  defaultFields = new List <FieldInfo>();

            foreach (var field in type.GetFields())
            {
                string caseExpr;


                if (MarshalingDescriptor.TryGetAttribute <string>(field,
                                                                  typeof(CaseAttribute), "expr", out caseExpr))
                {
                    IList <int?> caseValues = marshaler.EvaluateConstant(caseExpr);

                    int switchValue = marshaler.Evaluate(switchExpr);

                    if (caseValues.Contains(switchValue))
                    {
                        fieldsToCheck.Add(field);
                    }
                }
                else if (field.GetCustomAttributes(typeof(CaseDefaultAttribute), false).Length != 0)
                {
                    defaultFields.Add(field);
                }
            }

            if (fieldsToCheck.Count == 0)
            {
                fieldsToCheck.AddRange(defaultFields);
            }

            foreach (var field in fieldsToCheck)
            {
                object fieldValue = field.GetValue(value);
                if (IsStruct(field.GetType()))
                {
                    CheckPossibleValue(fieldValue, field);
                }
                else if (HasPossibleValue(field))
                {
                    CheckFieldValue(fieldValue, field);
                }
            }
        }
        public void Initialize <T>(ref T value)
        {
            lock (messageUtilsLock)
            {
                object obj = (object)value;
                Type   t   = typeof(T);
                marshaler.EnterContext();
                foreach (FieldInfo field in
                         t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
                {
                    Type ft = field.FieldType;
                    if (ft.IsEnum)
                    {
                        bool exclusive = !MarshalingDescriptor.HasAttribute(ft, typeof(FlagsAttribute));

                        if (exclusive)
                        {
                            FieldInfo[] df =
                                ft.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
                            if (df != null && df.Length > 0)
                            {
                                field.SetValue(obj, df[0].GetRawConstantValue());
                            }
                        }
                    }
                    else if (ft.IsArray)
                    {
                        int size, length;
                        marshaler.GetAdvocatedSize(new MarshalingDescriptor(ft, field), out size, out length);
                        if (size >= 0)
                        {
                            if (ft.IsArray)
                            {
                                field.SetValue(obj, Array.CreateInstance(ft.GetElementType(), size));
                            }
                            else
                            {
                                field.SetValue(obj, CreateSequence(ft.GetGenericArguments()[0], size));
                            }
                        }
                    }
                    marshaler.DefineSymbol(field.Name, field.GetValue(obj));
                }
                marshaler.ExitContext();

                List <MethodInfo> ms;
                if (initializers.TryGetValue(t, out (ms)))
                {
                    foreach (MethodInfo m in ms)
                    {
                        object[] args = new object[] { obj };
                        m.Invoke(this, args);
                        obj = args[0];
                    }
                }

                value = (T)obj;
            }
        }
        /// <summary>
        /// Create native marshaller.
        /// </summary>
        /// <param name="type">Type of struct.</param>
        /// <param name="switchValue">Switch attribute value if presents.</param>
        /// <param name="sizeValue">Size attribute value if presents.</param>
        /// <param name="lengthValue">Length attribute value if presents.</param>
        /// <param name="marshalDesccriptor">marshal descriptor</param>
        /// <returns>created marshaller</returns>
        private static Marshaler CreateNativeMarshaller(
            Type type,
            object switchValue,
            object sizeValue,
            object lengthValue,
            bool force32Bit,
            int align,
            out MarshalingDescriptor marshalDesccriptor
            )
        {
            MarshalingConfiguration mc = NativeMarshalingConfiguration.Configuration;

            if (align != -1)
            {
                mc.Alignment = align;
            }
            if (force32Bit)
            {
                mc.IntPtrSize = 4;
            }
            Marshaler marshaller = new Marshaler(mc);

            SwitchAttribute switchAttr = null;
            SizeAttribute   sizeAttr   = null;
            LengthAttribute lengthAttr = null;
            string          nameSuffix = DateTime.UtcNow.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture);

            if (switchValue != null)
            {
                string switchSymbolName = "switch_" + nameSuffix;
                marshaller.DefineSymbol(switchSymbolName, switchValue);
                switchAttr = new SwitchAttribute(switchSymbolName);
            }
            if (sizeValue != null)
            {
                string sizeSymbolName = "size_" + nameSuffix;
                marshaller.DefineSymbol(sizeSymbolName, sizeValue);
                sizeAttr = new SizeAttribute(sizeSymbolName);
            }
            if (lengthValue != null)
            {
                string lengthSymbolName = "length_" + nameSuffix;
                marshaller.DefineSymbol(lengthSymbolName, lengthValue);
                lengthAttr = new LengthAttribute(lengthSymbolName);
            }
            TypeCustomAttributeProvider attrProvider
                = new TypeCustomAttributeProvider(switchAttr, sizeAttr, lengthAttr);

            marshalDesccriptor = new MarshalingDescriptor(type, attrProvider);

            return(marshaller);
        }
            internal RpcParameter(ParameterInfo paramInfo,
                                  Type paramType,
                                  Type nativeType)
            {
                Type t = paramType;

                if (paramType.Name == "Nullable`1")
                {
                    t = paramType.GetGenericArguments()[0];
                }

                this.context           = new MarshalingDescriptor(t, paramInfo);
                this.IsByRef           = paramInfo.ParameterType.IsByRef;
                this.IsOut             = paramInfo.IsOut;
                this.nativeType        = nativeType;
                this.marshallingRegion = null;
            }
        Type GetNativeType(ParameterInfo paramInfo, Type type)
        {
            if (type == typeof(void))
            {
                return(type);
            }

            MarshalingDescriptor desc = new MarshalingDescriptor(type, paramInfo);
            Type nativeType           = msr.GetNativeType(desc);

            if (nativeType == null)
            {
                msr.TestAssumeFail(desc,
                                   "Unsupported native type representation. (You can use [Indirect] to pass a pointer.)",
                                   paramInfo.Name, type);
            }
            return(nativeType);
        }
        public bool CheckValueByEnum(Object value, Type type)
        {
            object obj = (object)value;
            Type   t   = type;

            bool exclusive = !MarshalingDescriptor.HasAttribute(t, typeof(FlagsAttribute));

            if (exclusive)
            {
                try
                {
                    if (!Enum.IsDefined(t, obj))
                    {
                        return(false);
                    }
                }
                catch (InvalidOperationException ex)
                {
                    if (host != null)
                    {
                        host.Assert(false, ex.ToString());
                    }
                }
            }
            else
            {
                object x = value;

                foreach (object v in Enum.GetValues(t))
                {
                    x = ExcludeBits(x, v);
                }

                if (!HasNoBits(x))
                {
                    return(false);
                }
            }

            return(true);
        }
 /// <summary>
 /// Computes the alignment of the given marshaling descriptor. 
 /// It is the delegate to the configured type marshaler.
 /// </summary>
 /// <param name="descriptor">The marshaling descriptor.</param>
 /// <returns>The alignment.</returns>
 public int GetAlignment(MarshalingDescriptor descriptor)
 {
     ITypeMarshaler msr = GetMarshaler(descriptor);
     return msr.GetAlignment(this, descriptor);
 }
 /// <summary>
 /// Test case assume fails with marshaling description, a given message, and additional parameters.
 /// </summary>
 /// <param name="desc">Marshaling descriptor</param>
 /// <param name="message">The given message</param>
 /// <param name="parameters">Additional parameters</param>
 public void TestAssumeFail(MarshalingDescriptor desc, string message, params object[] parameters)
 {
     string failedMessage = GetMessage(desc, message, parameters);
     if (host != null)
     {
         host.Assume(false, failedMessage);
     }
     else
     {
         Console.WriteLine(failedMessage);
         throw new InvalidOperationException(failedMessage);
     }
 }
            internal RpcParameter(ParameterInfo paramInfo,
                                  Type paramType,
                                  Type nativeType)
            {
                Type t = paramType;
                if (paramType.Name == "Nullable`1")
                {
                    t = paramType.GetGenericArguments()[0];
                }

                this.context = new MarshalingDescriptor(t, paramInfo);
                this.IsByRef = paramInfo.ParameterType.IsByRef;
                this.IsOut = paramInfo.IsOut;
                this.nativeType = nativeType;
                this.marshallingRegion = null;
            }
 /// <summary>
 /// Unmarshals the given value. 
 /// It is the delegate to the configured type marshaler.
 /// </summary>
 /// <param name="descriptor">The marshaling descriptor.</param>
 /// <returns>The unmarshaled value.</returns>
 public object Unmarshal(MarshalingDescriptor descriptor)
 {
     Trace("unmarshaling {0}", descriptor);
     ITypeMarshaler msr = GetMarshaler(descriptor);
     if (msr.GetType() != typeof(BitMarshaler))
     {
         CheckBitAlignment();
     }
     return msr.Unmarshal(this, descriptor);
 }
 /// <summary>
 /// Inherit from IEvaluationContext, currently not used in Marshaler.
 /// </summary>
 /// <param name="typeName">The custom type to be resolved</param>
 /// <param name="size">The actual size of the custom type</param>
 /// <returns>Returns true if it resolves the type successfully.</returns>
 public bool TryResolveCustomType(string typeName, out string size)
 {
     object type;
     if (customTypes.TryGetValue(typeName, out type))
     {
         Type customType = (Type)type;
         MarshalingDescriptor descriptor = new MarshalingDescriptor(customType);
         ITypeMarshaler msr = GetMarshaler(descriptor);
         size = msr.GetSize(this, descriptor, null).ToString(CultureInfo.InvariantCulture);
         return true;
     }
     else
     {
         size = "0";
         return false;
     }
 }
 /// <summary>
 /// Marshals the given value. 
 /// It is the delegate to the configured type marshaler.
 /// </summary>
 /// <param name="descriptor">The marshaling descriptor.</param>
 /// <param name="value">The value to be marshaled.</param>
 /// <returns></returns>
 public void Marshal(MarshalingDescriptor descriptor, object value)
 {
     Trace("marshaling {0}", descriptor);
     ITypeMarshaler msr = GetMarshaler(descriptor);
     if (msr.GetType() != typeof(BitMarshaler))
     {
         CheckBitAlignment();
     }
     msr.Marshal(this, descriptor, value);
 }
 /// <summary>
 /// Marshals the given value into the specified region.
 /// This method enters the region, delegates to the configured type marshaler, and exits the region.
 /// </summary>
 /// <param name="descriptor">The marshaling descriptor.</param>
 /// <param name="customRegion">The custom region.</param>
 /// <param name="value">The value to be marshaled.</param>
 public void MarshalInto(MarshalingDescriptor descriptor, IRegion customRegion, object value)
 {
     Trace("marshaling {0}", descriptor);
     EnterRegion(customRegion);
     ITypeMarshaler msr = GetMarshaler(descriptor);
     msr.Marshal(this, descriptor, value);
     CheckBitAlignment();
     ExitRegion();
 }
 /// <summary>
 /// Gets the native type of the given marshaling descriptor, if any. 
 /// It is the delegate to the configured type marshaler.
 /// </summary>
 /// <param name="descriptor">The marshaling descriptor.</param>
 /// <returns>The native type.</returns>
 public Type GetNativeType(MarshalingDescriptor descriptor)
 {
     ITypeMarshaler msr = GetMarshaler(descriptor);
     return msr.GetNativeType(this, descriptor);
 }
 /// <summary>
 /// Computes the size of the given marshaling descriptor and value. 
 /// It is the delegate to the configured type marshaler.
 /// If the size depends on the value and the value is unknown (null), a negative value maybe returned.
 /// </summary>
 /// <param name="descriptor">The marshaling descriptor.</param>
 /// <param name="value">The value.</param>
 /// <returns>The size of the given value.</returns>
 public int GetSize(MarshalingDescriptor descriptor, object value)
 {
     ITypeMarshaler msr = GetMarshaler(descriptor);
     return msr.GetSize(this, descriptor, value);
 }
        Type GetNativeType(ParameterInfo paramInfo, Type type)
        {
            if (type == typeof(void))
                return type;

            MarshalingDescriptor desc = new MarshalingDescriptor(type, paramInfo);
            Type nativeType = msr.GetNativeType(desc);
            if (nativeType == null)
                msr.TestAssumeFail(desc,
                    "Unsupported native type representation. (You can use [Indirect] to pass a pointer.)",
                    paramInfo.Name, type);
            return nativeType;
        }
        public void GetMultipleAdvocatedSizes(MarshalingDescriptor descriptor,
                                     out IList<int> sizes, out IList<int> lengths)
        {
            string sizeExpr;
            sizes = new List<int>();
            lengths = new List<int>();
            int size;

            // Evaluate static size expression
            if (MarshalingDescriptor.TryGetAttribute<int>(descriptor.Attributes, typeof(StaticSizeAttribute),
                                          "size", out size))
            {
                StaticSizeMode mode;
                if (!MarshalingDescriptor.TryGetAttribute<StaticSizeMode>(descriptor.Attributes,
                                                                                typeof(StaticSizeAttribute),
                                          "mode", out mode))
                    throw new InvalidOperationException("expected mode field in static size attribute");
                if (mode == StaticSizeMode.Bytes)
                {
                    Type elementType;
                    if (descriptor.Type.IsArray)
                        elementType = descriptor.Type.GetElementType();
                    else
                        elementType = descriptor.Type.GetGenericArguments()[0];
                    int s = GetSize(new MarshalingDescriptor(elementType), Activator.CreateInstance(elementType));
                    if (s < 0)
                        TestAssumeFail(descriptor, "must be able to determine size of element type");
                    size /= s;
                }

                if (size < 0)
                    TestAssumeFail(descriptor, "invalide static size '{0}'",
                                                size);
                sizes.Add(size);
            }

            // Evaluate size expression
            if (MarshalingDescriptor.TryGetAttribute<string>(
                            descriptor.Attributes, typeof(SizeAttribute),
                            "expr", out sizeExpr))
            {
                if (sizes.Count > 0)
                    TestAssumeFail(descriptor, "invalid combination of static with dynamic size");

                IList<int?> nullableSizes = this.EvaluateSizeExpression(sizeExpr, descriptor);

                if (nullableSizes.Count > 0 && nullableSizes[0] == null)
                {
                    nullableSizes[0] = 1;
                }
                foreach (int? value in nullableSizes)
                {
                    if (value == null)
                    {
                        TestAssertFail(descriptor, "invalid dynamic size expression '{0}'", sizeExpr);
                    }

                    if (value < 0)
                    {
                        TestAssertFail(descriptor, "invalid dynamic size '{0}'", value);
                    }

                    sizes.Add((int)value);
                }
            }

            // Evaluate length expression
            if (MarshalingDescriptor.TryGetAttribute<string>(
                            descriptor.Attributes, typeof(LengthAttribute),
                            "expr", out sizeExpr))
            {
                IList<int?> nullableLengths = this.EvaluateMultipleExpressions(sizeExpr);
                if (nullableLengths.Count != sizes.Count)
                {
                    TestAssertFail(descriptor, "the number of size values in size attribute is different from the number of length values in length attribute");
                }

                if (nullableLengths.Count > 0 && nullableLengths[0] == null)
                {
                    nullableLengths[0] = 1;
                }

                for (int i = 0; i < nullableLengths.Count; i++)
                {
                    if (nullableLengths[i] == null)
                    {
                        TestAssertFail(descriptor, "invalid length expression '{0}'", sizeExpr);
                    }

                    lengths.Add((int)nullableLengths[i]);

                    if (lengths[i] < 0)
                        TestAssertFail(descriptor, "invalid length '{0}'", lengths[i]);

                    if (lengths[i] > sizes[i])
                        TestAssertFail(descriptor, "length '{0}' is greater than size '{1}'",
                                                    lengths[i], sizes[i]);
                }
            }

            if (sizes.Count == 0)
            {
                size = 1;
                sizes.Add(size);
                lengths.Add(size);
            }

            if (lengths.Count == 0)
            {
                lengths = sizes;
            }
        }
 /// <summary>
 /// Unmarshals the given value from the specified region. 
 /// This method enters the region, delegates to the configured type marshaler, and exits the region.
 /// </summary>
 /// <param name="descriptor">The marshaling descriptor.</param>
 /// <param name="customRegion">The custom region.</param>
 /// <returns>The unmarshaled value.</returns>
 public object UnmarshalFrom(MarshalingDescriptor descriptor, IRegion customRegion)
 {
     Trace("unmarshaling {0}", descriptor);
     EnterRegion(customRegion);
     ITypeMarshaler msr = GetMarshaler(descriptor);
     object r = msr.Unmarshal(this, descriptor);
     CheckBitAlignment();
     ExitRegion();
     return r;
 }
        /// <summary>
        /// Retrieves the advocated size and length of a marshaling descriptor by inspecting the
        /// attributes attached to it.
        /// </summary>
        /// <param name="descriptor">The marshaling descriptor.</param>
        /// <param name="size">The advocated size.</param>
        /// <param name="length">The advocated length.</param>
        public void GetAdvocatedSize(MarshalingDescriptor descriptor,
                                     out int size, out int length)
        {
            string sizeExpr;
            length = -1;
            if (MarshalingDescriptor.TryGetAttribute<int>(descriptor.Attributes, typeof(StaticSizeAttribute),
                                          "size", out size))
            {
                StaticSizeMode mode;
                if (!MarshalingDescriptor.TryGetAttribute<StaticSizeMode>(descriptor.Attributes,
                                                                                typeof(StaticSizeAttribute),
                                          "mode", out mode))
                    throw new InvalidOperationException("expected mode field in static size attribute");
                if (mode == StaticSizeMode.Bytes)
                {
                    Type elementType;
                    if (descriptor.Type.IsArray)
                        elementType = descriptor.Type.GetElementType();
                    else
                        elementType = descriptor.Type.GetGenericArguments()[0];
                    int s = GetSize(new MarshalingDescriptor(elementType), Activator.CreateInstance(elementType));
                    if (s < 0)
                        TestAssumeFail(descriptor, "must be able to determine size of element type");
                    size /= s;
                }

                if (size < 0)
                    TestAssumeFail(descriptor, "invalide static size '{0}'",
                                                size);
            }
            else
                size = -1;
            if (MarshalingDescriptor.TryGetAttribute<string>(
                            descriptor.Attributes, typeof(SizeAttribute),
                            "expr", out sizeExpr))
            {
                if (size >= 0)
                    TestAssumeFail(descriptor, "invalid combination of static with dynamic size");

                IList<int?> sizes = this.EvaluateSizeExpression(sizeExpr, descriptor);
                if (sizes.Count != 1)
                {
                    TestAssumeFail(descriptor, "size expression is invalid (expect one size value in the expression).");
                }

                if (sizes[0] == null)
                {
                    TestAssumeFail(descriptor, "evaluating size expression failed");
                }

                size = sizes[0].Value;

                if (size < 0)
                    TestAssertFail(descriptor, "invalid dynamic size '{0}'",
                                                size);
            }
            if (MarshalingDescriptor.TryGetAttribute<string>(
                            descriptor.Attributes, typeof(LengthAttribute),
                            "expr", out sizeExpr))
            {
                length = this.Evaluate(sizeExpr);
                if (length < 0)
                    TestAssertFail(descriptor, "invalid length '{0}'",
                                                length);
            }
            if (size < 0)
                size = length;
            if (size < 0)
                size = 1;
            if (length < 0)
                length = size;
            if (length > size)
                TestAssertFail(descriptor, "length '{0}' greater than size '{1}'",
                                            length, size);
        }
        /// <summary>
        /// Defines symbols
        /// </summary>
        /// <param name="fields">The fields corresponding to the symbols</param>
        /// <param name="value">The values corresponding to the symbols</param>
        public void DefineSymbols(FieldInfo[] fields, object value)
        {
            if (fields == null)
            {
                throw new ArgumentNullException("fields");
            }

            foreach (FieldInfo field in fields)
            {
                MarshalingDescriptor fdesc = new MarshalingDescriptor(field.FieldType, field);
                object fieldValue = field.GetValue(value);

                Type nt;
                try
                {
                    nt = GetNativeType(fdesc);
                }
                catch (InvalidOperationException) // some types does not have native type.
                {
                    nt = null;
                }

                if (nt == typeof(IntPtr))
                {
                    DefinePointerSymbol(field.Name, fieldValue);
                }
                else
                {
                    DefineSymbol(field.Name, fieldValue);
                }
            }
        }
        IList<int?> EvaluateSizeExpression(string sizeExpr, MarshalingDescriptor descriptor)
        {
            IList<int?> nullableSizes = new List<int?>();

            // Do custom calculation when the first char is '@'
            if (sizeExpr.StartsWith("@", StringComparison.OrdinalIgnoreCase))
            {
                if (descriptor.ContainerType == null)
                {
                    TestAssumeFail(descriptor, "cannot find the type which contains custom calculation method");
                }

                if (sizeExpr.Length < 2)
                {
                    TestAssumeFail(descriptor, "cannot find method name in the size expression");
                }
                // remove the first char '@' to get method name.
                string methodName = sizeExpr.Substring(1);

                MethodInfo method = descriptor.ContainerType.GetMethod(
                    methodName,
                    BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

                if (method == null)
                {
                    TestAssumeFail(descriptor, "cannot find custom calculation method");
                }

                // Check the method signature.
                ParameterInfo[] paramInfos = method.GetParameters();
                if (paramInfos.Length == 1
                    && paramInfos[0].ParameterType == typeof(IEvaluationContext)
                    && method.ReturnParameter.ParameterType == typeof(int))
                {
                    int customSize = (int)method.Invoke(null, new object[] { this });
                    nullableSizes.Add(customSize);
                }
                else
                {
                    TestAssumeFail(descriptor, "the custom calculation method signature is invalid");
                }
            }
            else
            {
                nullableSizes = this.EvaluateMultipleExpressions(sizeExpr);
            }

            return nullableSizes;
        }
 static string GetMessage(MarshalingDescriptor desc, string message, params object[] parameters)
 {
     string failMessage = parameters.Length > 0 ? String.Format(CultureInfo.InvariantCulture, message, parameters) : message;
     if (desc.Type != null)
     {
         failMessage = string.Format(CultureInfo.InvariantCulture, "while processing '{0}': {1}", desc, failMessage);
     }
     return failMessage;
 }
 /// <summary>
 /// Returns the type marshaler determined by the marshaling configuration.
 /// </summary>
 /// <param name="descriptor">The marshaling descriptor.</param>
 /// <returns>The type marshaler.</returns>
 public ITypeMarshaler GetMarshaler(MarshalingDescriptor descriptor)
 {
     return config.GetMarshaler(this, descriptor);
 }
 /// <summary>
 /// Test case assert fails with marshaling description, a given message, and additional parameters.
 /// </summary>
 /// <param name="desc">Marshaling descriptor</param>
 /// <param name="message">The given message</param>
 /// <param name="parameters">Additional parameters</param>
 public void TestAssertFail(MarshalingDescriptor desc, string message, params object[] parameters)
 {
     if (host != null)
     {
         host.Assert(false, GetMessage(desc, message, parameters));
     }
     else
     {
         Console.WriteLine("FAIL: " + message);
         throw new InvalidOperationException(message);
     }
 }