1 /*
2  * Copyright 2019 by its authors. See AUTHORS.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef EOLIAN_MONO_MARSHALL_TYPE_HH
17 #define EOLIAN_MONO_MARSHALL_TYPE_HH
18 
19 #include "grammar/generator.hpp"
20 #include "grammar/klass_def.hpp"
21 #include "grammar/case.hpp"
22 
23 namespace eolian_mono {
24 
25 namespace attributes = efl::eolian::grammar::attributes;
26 namespace detail {
27 template <typename OutputIterator, typename Context>
28 struct marshall_type_visitor_generate;
29 template <typename OutputIterator, typename Context>
30 struct marshall_annotation_visitor_generate;
31 }
32 
33 /*
34  * Converts a given type/parameter to the type used in the DllImport signatures.
35  *
36  * For example, Eina.Value can be marshaled either as an eina.Value instance through
37  * CustomMarshallers if we have a ptr(Eina.Value) or through the intermediate
38  * eina.ValueNative blittable struct if it is passed by value.
39  *
40  * For details, check marshall_type_impl.h with the actual conversion rules.
41  */
42 struct marshall_type_generator
43 {
marshall_type_generatoreolian_mono::marshall_type_generator44    marshall_type_generator(bool is_return = false, bool is_special_subtype = false)
45      : is_return(is_return)
46      , is_special_subtype(is_special_subtype)
47    {}
48 
49    template <typename OutputIterator, typename Context>
generateeolian_mono::marshall_type_generator50    bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
51    {
52       return type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{
53         sink
54         , &context
55         , type.c_type
56         , false
57         , is_return
58         , type.is_ptr
59         , is_special_subtype
60       });
61    }
62    /* Some types may require a different conversion when they are in @out parameters. */
63    template <typename OutputIterator, typename Context>
generateeolian_mono::marshall_type_generator64    bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
65    {
66       return param.type.original_type.visit(detail::marshall_type_visitor_generate<OutputIterator, Context>{
67         sink
68         , &context
69         , param.type.c_type
70         , param.direction != attributes::parameter_direction::in
71         , false
72         , param.type.is_ptr
73         , is_special_subtype
74       });
75    }
76 
77    bool is_return;
78    bool is_special_subtype;
79 };
80 
81 /*
82  * Generates the "[MarshalAs(...)]" rules for the given type.
83  *
84  * For example, the CustomMarshallers definitions for String and eina.Values and the
85  * boolean size defintion (Eina_Value is 1 byte, while C# bool has 4 bytes).
86  */
87 struct marshall_annotation_generator
88 {
marshall_annotation_generatoreolian_mono::marshall_annotation_generator89    marshall_annotation_generator(bool is_return = false)
90      : is_return(is_return) {}
91 
92    template <typename OutputIterator, typename Context>
generateeolian_mono::marshall_annotation_generator93    bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
94    {
95       return type.original_type.visit(detail::marshall_annotation_visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr});
96    }
97    template <typename OutputIterator, typename Context>
generateeolian_mono::marshall_annotation_generator98    bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
99    {
100       return param.type.original_type.visit(detail::marshall_annotation_visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
101             , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
102    }
103 
104    bool is_return;
105 };
106 
107 struct marshall_type_terminal
108 {
operator ()eolian_mono::marshall_type_terminal109   marshall_type_generator const operator()(bool is_return, bool is_special_subtype = false) const
110   {
111     return marshall_type_generator(is_return, is_special_subtype);
112   }
113 } const marshall_type = {};
114 
as_generator(marshall_type_terminal)115 marshall_type_generator const as_generator(marshall_type_terminal)
116 {
117   return marshall_type_generator{};
118 }
119 
120 struct marshall_annotation_terminal
121 {
operator ()eolian_mono::marshall_annotation_terminal122   marshall_annotation_generator const operator()(bool is_return) const
123   {
124     return marshall_annotation_generator(is_return);
125   }
126 } const marshall_annotation = {};
127 
as_generator(marshall_annotation_terminal)128 marshall_annotation_generator const as_generator(marshall_annotation_terminal)
129 {
130   return marshall_annotation_generator{};
131 }
132 
133 
134 }
135 
136 namespace efl { namespace eolian { namespace grammar {
137 
138 template <>
139 struct is_eager_generator< ::eolian_mono::marshall_type_generator> : std::true_type {};
140 template <>
141 struct is_generator< ::eolian_mono::marshall_type_generator> : std::true_type {};
142 template <>
143 struct is_generator< ::eolian_mono::marshall_type_terminal> : std::true_type {};
144 
145 namespace type_traits {
146 template <>
147 struct attributes_needed< ::eolian_mono::marshall_type_generator> : std::integral_constant<int, 1> {};
148 template <>
149 struct attributes_needed< ::eolian_mono::marshall_type_terminal> : std::integral_constant<int, 1> {};
150 }
151 
152 template <>
153 struct is_eager_generator< ::eolian_mono::marshall_annotation_generator> : std::true_type {};
154 template <>
155 struct is_generator< ::eolian_mono::marshall_annotation_generator> : std::true_type {};
156 template <>
157 struct is_generator< ::eolian_mono::marshall_annotation_terminal> : std::true_type {};
158 
159 namespace type_traits {
160 template <>
161 struct attributes_needed< ::eolian_mono::marshall_annotation_generator> : std::integral_constant<int, 1> {};
162 template <>
163 struct attributes_needed< ::eolian_mono::marshall_annotation_terminal> : std::integral_constant<int, 1> {};
164 
165 }
166 
167 } } }
168 
169 #endif
170