TypeBuilder_h.template 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // This file is generated by TypeBuilder_h.template.
  2. // Copyright (c) 2016 The Chromium Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style license that can be
  4. // found in the LICENSE file.
  5. #ifndef {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h
  6. #define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h
  7. {% if config.protocol.export_header %}
  8. #include {{format_include(config.protocol.export_header)}}
  9. {% endif %}
  10. #include {{format_include(config.protocol.package, "Protocol")}}
  11. // For each imported domain we generate a ValueConversions struct instead of a full domain definition
  12. // and include Domain::API version from there.
  13. {% for name in domain.dependencies %}
  14. {% if protocol.is_imported_dependency(name) %}
  15. #include {{format_domain_include(config.protocol.package, name)}}
  16. {% endif %}
  17. {% endfor %}
  18. {% if protocol.is_exported_domain(domain.domain) %}
  19. #include {{format_include(config.exported.package, domain.domain)}}
  20. {% endif %}
  21. {% for namespace in config.protocol.namespace %}
  22. namespace {{namespace}} {
  23. {% endfor %}
  24. namespace {{domain.domain}} {
  25. {% for type in domain.types %}
  26. {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
  27. {% if type.type == "object" %}
  28. {% if "properties" in type %}
  29. class {{type.id}};
  30. {% else %}
  31. using {{type.id}} = Object;
  32. {% endif %}
  33. {% elif type.type != "array" %}
  34. using {{type.id}} = {{protocol.resolve_type(type).type}};
  35. {% endif %}
  36. {% endfor %}
  37. // ------------- Forward and enum declarations.
  38. {% for type in domain.types %}
  39. {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
  40. {% if "enum" in type %}
  41. namespace {{type.id}}Enum {
  42. {% for literal in type.enum %}
  43. {{config.protocol.export_macro}} extern const char {{ literal | dash_to_camelcase}}[];
  44. {% endfor %}
  45. } // namespace {{type.id}}Enum
  46. {% endif %}
  47. {% endfor %}
  48. {% for command in join_arrays(domain, ["commands", "events"]) %}
  49. {% for param in join_arrays(command, ["parameters", "returns"]) %}
  50. {% if "enum" in param %}
  51. namespace {{command.name | to_title_case}} {
  52. namespace {{param.name | to_title_case}}Enum {
  53. {% for literal in param.enum %}
  54. {{config.protocol.export_macro}} extern const char* {{literal | dash_to_camelcase}};
  55. {% endfor %}
  56. } // {{param.name | to_title_case}}Enum
  57. } // {{command.name | to_title_case }}
  58. {% endif %}
  59. {% endfor %}
  60. {% endfor %}
  61. // ------------- Type and builder declarations.
  62. {% for type in domain.types %}
  63. {% if not protocol.generate_type(domain.domain, type.id) %}{% continue %}{% endif %}
  64. {% if not (type.type == "object") or not ("properties" in type) %}{% continue %}{% endif %}
  65. class {{config.protocol.export_macro}} {{type.id}} : public ::{{config.crdtp.namespace}}::ProtocolObject<{{type.id}}>{% if protocol.is_exported(domain.domain, type.id) %},
  66. public API::{{type.id}}{% endif %} {
  67. public:
  68. ~{{type.id}}() override { }
  69. {% for property in type.properties %}
  70. {% set property_type = protocol.resolve_type(property) %}
  71. {% set property_name = property.name | to_title_case %}
  72. {% set property_field = "m_" + property.name %}
  73. {% if "enum" in property %}
  74. struct {{config.protocol.export_macro}} {{property_name}}Enum {
  75. {% for literal in property.enum %}
  76. static const char* {{literal | dash_to_camelcase}};
  77. {% endfor %}
  78. }; // {{property_name}}Enum
  79. {% endif %}
  80. {% if property.optional %}
  81. bool {{"has" | to_method_case}}{{property_name}}() { return {{property_field}}.isJust(); }
  82. {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}({{property_type.raw_pass_type}} defaultValue) { return {{property_field}}.isJust() ? {{property_field}}.fromJust() : defaultValue; }
  83. {% else %}
  84. {{property_type.raw_return_type}} {{"get" | to_method_case}}{{property_name}}() { return {{property_type.to_raw_type % property_field}}; }
  85. {% endif %}
  86. void {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value) { {{property_field}} = {{property_type.to_rvalue % "value"}}; }
  87. {% endfor %}
  88. template<int STATE>
  89. class {{type.id}}Builder {
  90. public:
  91. enum {
  92. NoFieldsSet = 0,
  93. {% for property in type.properties|rejectattr("optional") %}
  94. {{property.name | to_title_case}}Set = 1 << {{loop.index}},
  95. {% endfor %}
  96. AllFieldsSet = (
  97. {%- for property in type.properties %}
  98. {% if not(property.optional) %}{{property.name | to_title_case}}Set | {%endif %}
  99. {% endfor %}0)};
  100. {% for property in type.properties %}
  101. {% set property_type = protocol.resolve_type(property) %}
  102. {% set property_name = property.name | to_title_case %}
  103. {% if property.optional %}
  104. {{type.id}}Builder<STATE>& {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value)
  105. {
  106. m_result->{{"set" | to_method_case}}{{property_name}}({{property_type.to_rvalue % "value"}});
  107. return *this;
  108. }
  109. {% else %}
  110. {{type.id}}Builder<STATE | {{property_name}}Set>& {{"set" | to_method_case}}{{property_name}}({{property_type.pass_type}} value)
  111. {
  112. static_assert(!(STATE & {{property_name}}Set), "property {{property.name}} should not be set yet");
  113. m_result->{{"set" | to_method_case}}{{property_name}}({{property_type.to_rvalue % "value"}});
  114. return castState<{{property_name}}Set>();
  115. }
  116. {% endif %}
  117. {% endfor %}
  118. std::unique_ptr<{{type.id}}> {{"build" | to_method_case}}()
  119. {
  120. static_assert(STATE == AllFieldsSet, "state should be AllFieldsSet");
  121. return std::move(m_result);
  122. }
  123. private:
  124. friend class {{type.id}};
  125. {{type.id}}Builder() : m_result(new {{type.id}}()) { }
  126. template<int STEP> {{type.id}}Builder<STATE | STEP>& castState()
  127. {
  128. return *reinterpret_cast<{{type.id}}Builder<STATE | STEP>*>(this);
  129. }
  130. {{protocol.type_definition(domain.domain + "." + type.id).type}} m_result;
  131. };
  132. static {{type.id}}Builder<0> {{"create" | to_method_case}}()
  133. {
  134. return {{type.id}}Builder<0>();
  135. }
  136. private:
  137. DECLARE_SERIALIZATION_SUPPORT();
  138. {{type.id}}()
  139. {
  140. {% for property in type.properties %}
  141. {% if not(property.optional) and "default_value" in protocol.resolve_type(property) %}
  142. m_{{property.name}} = {{protocol.resolve_type(property).default_value}};
  143. {%endif %}
  144. {% endfor %}
  145. }
  146. {% for property in type.properties %}
  147. {% if property.optional %}
  148. Maybe<{{protocol.resolve_type(property).raw_type}}> m_{{property.name}};
  149. {% else %}
  150. {{protocol.resolve_type(property).type}} m_{{property.name}};
  151. {% endif %}
  152. {% endfor %}
  153. };
  154. {% endfor %}
  155. // ------------- Backend interface.
  156. class {{config.protocol.export_macro}} Backend {
  157. public:
  158. virtual ~Backend() { }
  159. {% for command in domain.commands %}
  160. {% if "redirect" in command %}{% continue %}{% endif %}
  161. {% if not protocol.generate_command(domain.domain, command.name) %}{% continue %}{% endif %}
  162. {% if protocol.is_async_command(domain.domain, command.name) %}
  163. class {{config.protocol.export_macro}} {{command.name | to_title_case}}Callback {
  164. public:
  165. virtual void sendSuccess(
  166. {%- for parameter in command.returns -%}
  167. {%- if "optional" in parameter -%}
  168. Maybe<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}}
  169. {%- else -%}
  170. {{protocol.resolve_type(parameter).pass_type}} {{parameter.name}}
  171. {%- endif -%}
  172. {%- if not loop.last -%}, {% endif -%}
  173. {%- endfor -%}
  174. ) = 0;
  175. virtual void sendFailure(const DispatchResponse&) = 0;
  176. virtual void fallThrough() = 0;
  177. virtual ~{{command.name | to_title_case}}Callback() { }
  178. };
  179. {% endif %}
  180. {%- if not protocol.is_async_command(domain.domain, command.name) %}
  181. virtual DispatchResponse {{command.name | to_method_case}}(
  182. {%- else %}
  183. virtual void {{command.name | to_method_case}}(
  184. {%- endif %}
  185. {%- for parameter in command.parameters -%}
  186. {%- if not loop.first -%}, {% endif -%}
  187. {%- if "optional" in parameter -%}
  188. Maybe<{{protocol.resolve_type(parameter).raw_type}}> in_{{parameter.name}}
  189. {%- else -%}
  190. {{protocol.resolve_type(parameter).pass_type}} in_{{parameter.name}}
  191. {%- endif -%}
  192. {%- endfor -%}
  193. {%- if protocol.is_async_command(domain.domain, command.name) -%}
  194. {%- if command.parameters -%}, {% endif -%}
  195. std::unique_ptr<{{command.name | to_title_case}}Callback> callback
  196. {%- else -%}
  197. {%- for parameter in command.returns -%}
  198. {%- if (not loop.first) or command.parameters -%}, {% endif -%}
  199. {%- if "optional" in parameter -%}
  200. Maybe<{{protocol.resolve_type(parameter).raw_type}}>* out_{{parameter.name}}
  201. {%- else -%}
  202. {{protocol.resolve_type(parameter).type}}* out_{{parameter.name}}
  203. {%- endif -%}
  204. {%- endfor -%}
  205. {%- endif -%}
  206. ) = 0;
  207. {% endfor %}
  208. {% if protocol.generate_disable(domain) %}
  209. virtual DispatchResponse {{"disable" | to_method_case}}()
  210. {
  211. return DispatchResponse::Success();
  212. }
  213. {% endif %}
  214. };
  215. // ------------- Frontend interface.
  216. class {{config.protocol.export_macro}} Frontend {
  217. public:
  218. explicit Frontend(FrontendChannel* frontend_channel) : frontend_channel_(frontend_channel) {}
  219. {% for event in domain.events %}
  220. {% if not protocol.generate_event(domain.domain, event.name) %}{% continue %}{% endif %}
  221. void {{event.name | to_method_case}}(
  222. {%- for parameter in event.parameters -%}
  223. {%- if "optional" in parameter -%}
  224. Maybe<{{protocol.resolve_type(parameter).raw_type}}> {{parameter.name}} = Maybe<{{protocol.resolve_type(parameter).raw_type}}>()
  225. {%- else -%}
  226. {{protocol.resolve_type(parameter).pass_type}} {{parameter.name}}
  227. {%- endif -%}{%- if not loop.last -%}, {% endif -%}
  228. {%- endfor -%}
  229. );
  230. {% endfor %}
  231. void flush();
  232. void sendRawNotification(std::unique_ptr<Serializable>);
  233. private:
  234. FrontendChannel* frontend_channel_;
  235. };
  236. // ------------- Dispatcher.
  237. class {{config.protocol.export_macro}} Dispatcher {
  238. public:
  239. static void wire(UberDispatcher*, Backend*);
  240. private:
  241. Dispatcher() { }
  242. };
  243. // ------------- Metainfo.
  244. class {{config.protocol.export_macro}} Metainfo {
  245. public:
  246. using BackendClass = Backend;
  247. using FrontendClass = Frontend;
  248. using DispatcherClass = Dispatcher;
  249. static const char domainName[];
  250. static const char commandPrefix[];
  251. static const char version[];
  252. };
  253. } // namespace {{domain.domain}}
  254. {% for namespace in config.protocol.namespace %}
  255. } // namespace {{namespace}}
  256. {% endfor %}
  257. #endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_h)