Example #1
0
        public IEnumerable <string> GetParameterDeclarations()
        {
            yield return("&self");

            foreach (var p in Method.Parameters)
            {
                Assert(!p.IsReturnValue);
                int?lengthIs          = null;
                var lengthIsAttribute = p.CustomAttributes.SingleOrDefault(a => a.AttributeType.Name == "LengthIsAttribute");
                if (lengthIsAttribute != null)
                {
                    lengthIs = (int)lengthIsAttribute.ConstructorArguments[0].Value;
                }

                if (p.ParameterType.IsArray)
                {
                    // need additional input size parameter (even if parameter is marked as [Out])
                    yield return(NameHelpers.FirstToLower(p.Name) + "Size: u32");
                }
                else if (p.ParameterType.IsByReference && (p.ParameterType as ByReferenceType).ElementType.IsArray)
                {
                    Assert(!lengthIs.HasValue);
                    // need additional output size parameter
                    yield return(NameHelpers.FirstToLower(p.Name) + "Size: *mut u32");
                }
                yield return(NameHelpers.PreventKeywords(NameHelpers.FirstToLower(p.Name)) + ": " + TypeHelpers.GetTypeName(DeclaringType.Generator, this, p.ParameterType, TypeUsage.Raw));
            }
            if (Method.ReturnType.FullName != "System.Void")
            {
                if (Method.ReturnType.IsArray)
                {
                    yield return("outSize: *mut u32");
                }
                yield return("out: *mut " + TypeHelpers.GetTypeName(DeclaringType.Generator, this, Method.ReturnType, TypeUsage.Raw));
            }
        }
Example #2
0
        public string MakeWrapperBody(MethodDefinition def, bool isFactoryMethod)
        {
            var  rawName      = RawName;
            bool isGetMany    = GetManyParameterName != null;
            var  getManyPname = GetManyParameterName;
            var  output       = Output;

            var rawParams = new List <string> {
                "self.get_abi() as *const _ as *mut _"
            };

            foreach (var p in def.Parameters)
            {
                var pname = NameHelpers.PreventKeywords(NameHelpers.FirstToLower(p.Name));
                if (p.ParameterType.IsByReference)
                {
                    if (((ByReferenceType)p.ParameterType).ElementType.IsArray)
                    {
                        rawParams.Add("&mut " + pname + "Size");
                    }

                    // output parameter
                    rawParams.Add("&mut " + pname);
                }
                else
                {
                    // input parameter
                    if (p.ParameterType.IsArray)
                    {
                        if (p.IsOut)
                        {
                            if (isGetMany)
                            {
                                rawParams.Add(pname + ".capacity() as u32");
                                rawParams.Add(pname + ".as_mut_ptr() as *mut T::Abi");
                            }
                            else
                            {
                                rawParams.Add(pname + ".len() as u32");
                                rawParams.Add(pname + ".as_mut_ptr() as *mut _");
                            }
                        }
                        else
                        {
                            rawParams.Add(pname + ".len() as u32");
                            rawParams.Add(pname + ".as_ptr() as *mut _");
                        }
                    }
                    else
                    {
                        rawParams.Add(TypeHelpers.UnwrapInputParameter(pname, p.ParameterType));
                    }
                }
            }

            if (def.ReturnType.FullName != "System.Void")
            {
                if (def.ReturnType.IsArray)
                {
                    rawParams.Add("&mut outSize");
                }
                rawParams.Add("&mut out");
            }

            var outInit = String.Join(" ", output.SelectMany(o => TypeHelpers.CreateUninitializedOutputs(o.Item1, o.Item2)));

            if (outInit != "")
            {
                outInit = "\r\n        " + outInit;
            }

            var outWrap = String.Join(", ", output.Zip(GeneratedOutTypes, (a, b) => Tuple.Create(a.Item1, a.Item2, a.Item3, b)).Select(o => TypeHelpers.WrapOutputParameter(o.Item1, o.Item2, isFactoryMethod || o.Item3, o.Item4)));

            if (output.Count != 1)
            {
                outWrap = "(" + outWrap + ")"; // also works for count == 0 (empty tuple)
            }
            outWrap = "Ok(" + outWrap + ")";

            if (isGetMany)
            {
                outInit = $"\r\n        debug_assert!({ getManyPname }.capacity() > 0, \"capacity of `{ getManyPname }` must not be 0 (use Vec::with_capacity)\"); { getManyPname }.clear();{ outInit }";
                outWrap = $"{ getManyPname }.set_len(out as usize); Ok(())";
            }

            return(outInit + $@"
        let hr = (self.get_vtbl().{ rawName })({ String.Join(", ", rawParams) });
        if hr == S_OK {{ { outWrap } }} else {{ err(hr) }}");
        }
Example #3
0
        private MethodDetailsCache InitializeDetailsCache()
        {
            string rawName = GetRawName();
            string name    = GetWrapperName(rawName);

            bool isGetMany = (rawName == "GetMany" && DeclaringType.Namespace == "Windows.Foundation.Collections" &&
                              (DeclaringType.Name == "IVectorView`1" || DeclaringType.Name == "IIterator`1" || DeclaringType.Name == "IVector`1"));
            string getManyPname = null;

            // These `GetMany` methods have special semantics, since it takes an array and returns the number of elements that were filled
            // It uses the __RPC__out_ecount_part(capacity, *actual) annotation in the C headers. For the wrapper we use a &mut Vec<> buffer.

            var input  = new List <Tuple <string, TypeReference, InputKind> >();
            var output = new List <Tuple <string, TypeReference, bool> >();

            foreach (var p in Method.Parameters)
            {
                string pname = NameHelpers.PreventKeywords(NameHelpers.FirstToLower(p.Name));
                if (p.ParameterType.IsByReference)
                {
                    Assert(p.IsOut);
                    var realType = ((ByReferenceType)p.ParameterType).ElementType;
                    output.Add(Tuple.Create(pname, realType, false));
                }
                else
                {
                    if (p.ParameterType.IsArray)
                    {
                        if (p.IsOut)
                        {
                            if (isGetMany)
                            {
                                Assert(getManyPname == null); // there should only be one out-array parameter for GetMany
                                getManyPname = pname;
                                input.Add(Tuple.Create(pname, ((ArrayType)p.ParameterType).ElementType, InputKind.VecBuffer));
                            }
                            else
                            {
                                input.Add(Tuple.Create(pname, ((ArrayType)p.ParameterType).ElementType, InputKind.MutSlice));
                            }
                        }
                        else
                        {
                            input.Add(Tuple.Create(pname, ((ArrayType)p.ParameterType).ElementType, InputKind.Slice));
                        }
                    }
                    else
                    {
                        input.Add(Tuple.Create(pname, p.ParameterType, InputKind.Default));
                    }
                }
            }

            if (Method.ReturnType.FullName != "System.Void")
            {
                // this makes the actual return value the last in the tuple (if multiple)
                output.Add(Tuple.Create("out", Method.ReturnType, TypeHelpers.IsReturnTypeNonNull(Method.ReturnType, DeclaringType.Generator)));
            }

            // TODO: second tuple element should be true for some method's return value
            var outTypes = output.Select(o => Tuple.Create(o.Item2, o.Item3)).ToArray();

            if (isGetMany)
            {
                outTypes = new Tuple <TypeReference, bool>[] { }; // GetMany has no return value
            }



            return(new MethodDetailsCache
            {
                WrappedName = name,
                RawName = rawName,
                InputParameterNames = input.Select(i => i.Item1).ToArray(),
                InputParameterTypes = input.Select(i => Tuple.Create(i.Item2, i.Item3)).ToArray(),
                OutTypes = outTypes.ToArray(),
                GetManyParameterName = isGetMany ? getManyPname : null,
                Output = output
            });
        }