| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-24 15:28:26 +01:00
										 |  |  | #include <AK/Debug.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:29:06 +01:00
										 |  |  | #include <AK/Function.h>
 | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  | #include <AK/GenericLexer.h>
 | 
					
						
							| 
									
										
										
										
											2019-08-03 16:18:37 +02:00
										 |  |  | #include <AK/HashMap.h>
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | #include <AK/SourceGenerator.h>
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | #include <AK/StringBuilder.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-06 15:04:03 +01:00
										 |  |  | #include <LibCore/File.h>
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  | #ifndef GENERATE_DEBUG_CODE
 | 
					
						
							|  |  |  | #    define GENERATE_DEBUG_CODE 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | struct Parameter { | 
					
						
							| 
									
										
										
										
											2020-05-16 14:11:35 +02:00
										 |  |  |     Vector<String> attributes; | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |     String type; | 
					
						
							|  |  |  |     String name; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  | static String pascal_case(String const& identifier) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     bool was_new_word = true; | 
					
						
							|  |  |  |     for (auto ch : identifier) { | 
					
						
							|  |  |  |         if (ch == '_') { | 
					
						
							|  |  |  |             was_new_word = true; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (was_new_word) { | 
					
						
							|  |  |  |             builder.append(toupper(ch)); | 
					
						
							|  |  |  |             was_new_word = false; | 
					
						
							|  |  |  |         } else | 
					
						
							|  |  |  |             builder.append(ch); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return builder.to_string(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | struct Message { | 
					
						
							|  |  |  |     String name; | 
					
						
							|  |  |  |     bool is_synchronous { false }; | 
					
						
							|  |  |  |     Vector<Parameter> inputs; | 
					
						
							|  |  |  |     Vector<Parameter> outputs; | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     String response_name() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         StringBuilder builder; | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |         builder.append(pascal_case(name)); | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |         builder.append("Response"); | 
					
						
							|  |  |  |         return builder.to_string(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct Endpoint { | 
					
						
							| 
									
										
										
										
											2021-07-02 21:35:27 -07:00
										 |  |  |     Vector<String> includes; | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |     String name; | 
					
						
							| 
									
										
										
										
											2021-04-25 13:19:53 +02:00
										 |  |  |     u32 magic; | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |     Vector<Message> messages; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-07 18:50:00 +02:00
										 |  |  | static bool is_primitive_type(String const& type) | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-05-13 15:35:05 +02:00
										 |  |  |     return type.is_one_of("u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "bool", "double", "float", "int", "unsigned", "unsigned int"); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-07 18:50:00 +02:00
										 |  |  | static String message_name(String const& endpoint, String& message, bool is_response) | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     builder.append("Messages::"); | 
					
						
							|  |  |  |     builder.append(endpoint); | 
					
						
							|  |  |  |     builder.append("::"); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |     builder.append(pascal_case(message)); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |     if (is_response) | 
					
						
							|  |  |  |         builder.append("Response"); | 
					
						
							|  |  |  |     return builder.to_string(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | int main(int argc, char** argv) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (argc != 2) { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         outln("usage: {} <IPC endpoint definition file>", argv[0]); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |     auto file = Core::File::construct(argv[1]); | 
					
						
							| 
									
										
										
										
											2021-05-12 13:56:43 +04:30
										 |  |  |     if (!file->open(Core::OpenMode::ReadOnly)) { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         warnln("Error: Cannot open {}: {}", argv[1], file->error_string()); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-21 20:50:06 +02:00
										 |  |  |     auto file_contents = file->read_all(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |     GenericLexer lexer(file_contents); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Vector<Endpoint> endpoints; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |     auto assert_specific = [&](char ch) { | 
					
						
							|  |  |  |         if (lexer.peek() != ch) | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |             warnln("assert_specific: wanted '{}', but got '{}' at index {}", ch, lexer.peek(), lexer.tell()); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         bool saw_expected = lexer.consume_specific(ch); | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY(saw_expected); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto consume_whitespace = [&] { | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         lexer.ignore_while([](char ch) { return isspace(ch); }); | 
					
						
							|  |  |  |         if (lexer.peek() == '/' && lexer.peek(1) == '/') | 
					
						
							|  |  |  |             lexer.ignore_until([](char ch) { return ch == '\n'; }); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto parse_parameter = [&](Vector<Parameter>& storage) { | 
					
						
							|  |  |  |         for (;;) { | 
					
						
							|  |  |  |             Parameter parameter; | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             if (lexer.peek() == ')') | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             if (lexer.consume_specific('[')) { | 
					
						
							| 
									
										
										
										
											2020-05-16 14:11:35 +02:00
										 |  |  |                 for (;;) { | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |                     if (lexer.consume_specific(']')) { | 
					
						
							| 
									
										
										
										
											2020-05-16 14:11:35 +02:00
										 |  |  |                         consume_whitespace(); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |                     if (lexer.consume_specific(',')) { | 
					
						
							| 
									
										
										
										
											2020-05-16 14:11:35 +02:00
										 |  |  |                         consume_whitespace(); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |                     auto attribute = lexer.consume_until([](char ch) { return ch == ']' || ch == ','; }); | 
					
						
							| 
									
										
										
										
											2020-05-16 14:11:35 +02:00
										 |  |  |                     parameter.attributes.append(attribute); | 
					
						
							|  |  |  |                     consume_whitespace(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             parameter.type = lexer.consume_until([](char ch) { return isspace(ch); }); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |             consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             parameter.name = lexer.consume_until([](char ch) { return isspace(ch) || ch == ',' || ch == ')'; }); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |             consume_whitespace(); | 
					
						
							|  |  |  |             storage.append(move(parameter)); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             if (lexer.consume_specific(',')) | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             if (lexer.peek() == ')') | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto parse_parameters = [&](Vector<Parameter>& storage) { | 
					
						
							|  |  |  |         for (;;) { | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							|  |  |  |             parse_parameter(storage); | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             if (lexer.consume_specific(',')) | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             if (lexer.peek() == ')') | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto parse_message = [&] { | 
					
						
							|  |  |  |         Message message; | 
					
						
							|  |  |  |         consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         message.name = lexer.consume_until([](char ch) { return isspace(ch) || ch == '('; }); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         assert_specific('('); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         parse_parameters(message.inputs); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         assert_specific(')'); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         assert_specific('='); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         auto type = lexer.consume(); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         if (type == '>') | 
					
						
							|  |  |  |             message.is_synchronous = true; | 
					
						
							|  |  |  |         else if (type == '|') | 
					
						
							|  |  |  |             message.is_synchronous = false; | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |             VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         consume_whitespace(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (message.is_synchronous) { | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             assert_specific('('); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |             parse_parameters(message.outputs); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             assert_specific(')'); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         consume_whitespace(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         endpoints.last().messages.append(move(message)); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto parse_messages = [&] { | 
					
						
							|  |  |  |         for (;;) { | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |             if (lexer.peek() == '}') | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2021-06-23 17:00:38 +02:00
										 |  |  |             parse_message(); | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-02 21:35:27 -07:00
										 |  |  |     auto parse_include = [&] { | 
					
						
							|  |  |  |         String include; | 
					
						
							|  |  |  |         consume_whitespace(); | 
					
						
							|  |  |  |         include = lexer.consume_while([](char ch) { return ch != '\n'; }); | 
					
						
							|  |  |  |         consume_whitespace(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         endpoints.last().includes.append(move(include)); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto parse_includes = [&] { | 
					
						
							|  |  |  |         for (;;) { | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							|  |  |  |             if (lexer.peek() != '#') | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             parse_include(); | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |     auto parse_endpoint = [&] { | 
					
						
							|  |  |  |         endpoints.empend(); | 
					
						
							|  |  |  |         consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2021-07-02 21:35:27 -07:00
										 |  |  |         parse_includes(); | 
					
						
							|  |  |  |         consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         lexer.consume_specific("endpoint"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         endpoints.last().name = lexer.consume_while([](char ch) { return !isspace(ch); }); | 
					
						
							| 
									
										
										
										
											2021-04-25 13:19:53 +02:00
										 |  |  |         endpoints.last().magic = Traits<String>::hash(endpoints.last().name); | 
					
						
							| 
									
										
										
										
											2021-04-25 11:24:12 +02:00
										 |  |  |         consume_whitespace(); | 
					
						
							| 
									
										
										
										
											2021-04-25 13:19:53 +02:00
										 |  |  |         if (lexer.peek() == '[') { | 
					
						
							|  |  |  |             // This only supports a single parameter for now, and adding multiple
 | 
					
						
							|  |  |  |             // endpoint parameter support is left as an exercise for the reader. :^)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             lexer.consume_specific('['); | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto parameter = lexer.consume_while([](char ch) { return !isspace(ch) && ch != '='; }); | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							|  |  |  |             assert_specific('='); | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (parameter == "magic") { | 
					
						
							|  |  |  |                 // "magic" overwrites the default magic with a hardcoded one.
 | 
					
						
							|  |  |  |                 auto magic_string = lexer.consume_while([](char ch) { return !isspace(ch) && ch != ']'; }); | 
					
						
							|  |  |  |                 endpoints.last().magic = magic_string.to_uint().value(); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 warnln("parse_endpoint: unknown parameter '{}' passed", parameter); | 
					
						
							|  |  |  |                 VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             assert_specific(']'); | 
					
						
							|  |  |  |             consume_whitespace(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         assert_specific('{'); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         parse_messages(); | 
					
						
							| 
									
										
										
										
											2020-08-21 09:18:10 -04:00
										 |  |  |         assert_specific('}'); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         consume_whitespace(); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-21 10:39:46 -04:00
										 |  |  |     while (lexer.tell() < file_contents.size()) | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         parse_endpoint(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     SourceGenerator generator { builder }; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-02 21:35:27 -07:00
										 |  |  |     generator.append("#pragma once\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // This must occur before LibIPC/Decoder.h
 | 
					
						
							|  |  |  |     for (auto& endpoint : endpoints) { | 
					
						
							|  |  |  |         for (auto& include : endpoint.includes) { | 
					
						
							|  |  |  |             generator.append(include); | 
					
						
							|  |  |  |             generator.append("\n"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     generator.append(R"~~~(#include <AK/MemoryStream.h> | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | #include <AK/OwnPtr.h>
 | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  | #include <AK/Result.h>
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | #include <AK/Utf8View.h>
 | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | #include <LibIPC/Connection.h>
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | #include <LibIPC/Decoder.h>
 | 
					
						
							|  |  |  | #include <LibIPC/Dictionary.h>
 | 
					
						
							|  |  |  | #include <LibIPC/Encoder.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-21 21:59:12 +03:00
										 |  |  | #include <LibIPC/File.h>
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | #include <LibIPC/Message.h>
 | 
					
						
							| 
									
										
										
										
											2021-05-03 13:33:59 +02:00
										 |  |  | #include <LibIPC/Stub.h>
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (auto& endpoint : endpoints) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |         auto endpoint_generator = generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         endpoint_generator.set("endpoint.name", endpoint.name); | 
					
						
							|  |  |  |         endpoint_generator.set("endpoint.magic", String::number(endpoint.magic)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  | namespace Messages::@endpoint.name@ { | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 16:18:37 +02:00
										 |  |  |         HashMap<String, int> message_ids; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  | enum class MessageID : i32 { | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 16:18:37 +02:00
										 |  |  |         for (auto& message : endpoint.messages) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |             auto message_generator = endpoint_generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 16:18:37 +02:00
										 |  |  |             message_ids.set(message.name, message_ids.size() + 1); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |             message_generator.set("message.name", message.name); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |             message_generator.set("message.pascal_name", pascal_case(message.name)); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |             message_generator.set("message.id", String::number(message_ids.size())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |     @message.pascal_name@ = @message.id@, | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 16:18:37 +02:00
										 |  |  |             if (message.is_synchronous) { | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |                 message_ids.set(message.response_name(), message_ids.size() + 1); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 message_generator.set("message.name", message.response_name()); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |                 message_generator.set("message.pascal_name", pascal_case(message.response_name())); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 message_generator.set("message.id", String::number(message_ids.size())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |     @message.pascal_name@ = @message.id@, | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 16:18:37 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 16:18:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 16:35:49 +02:00
										 |  |  |         auto constructor_for_message = [&](const String& name, const Vector<Parameter>& parameters) { | 
					
						
							|  |  |  |             StringBuilder builder; | 
					
						
							|  |  |  |             builder.append(name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (parameters.is_empty()) { | 
					
						
							|  |  |  |                 builder.append("() {}"); | 
					
						
							|  |  |  |                 return builder.to_string(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             builder.append('('); | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |             for (size_t i = 0; i < parameters.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2019-08-03 16:35:49 +02:00
										 |  |  |                 auto& parameter = parameters[i]; | 
					
						
							|  |  |  |                 builder.append(parameter.type); | 
					
						
							| 
									
										
										
										
											2021-01-14 09:15:32 +01:00
										 |  |  |                 builder.append(" "); | 
					
						
							| 
									
										
										
										
											2019-08-03 16:35:49 +02:00
										 |  |  |                 builder.append(parameter.name); | 
					
						
							|  |  |  |                 if (i != parameters.size() - 1) | 
					
						
							|  |  |  |                     builder.append(", "); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             builder.append(") : "); | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |             for (size_t i = 0; i < parameters.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2019-08-03 16:35:49 +02:00
										 |  |  |                 auto& parameter = parameters[i]; | 
					
						
							|  |  |  |                 builder.append("m_"); | 
					
						
							|  |  |  |                 builder.append(parameter.name); | 
					
						
							| 
									
										
										
										
											2021-01-14 09:15:32 +01:00
										 |  |  |                 builder.append("(move("); | 
					
						
							| 
									
										
										
										
											2019-08-03 16:35:49 +02:00
										 |  |  |                 builder.append(parameter.name); | 
					
						
							| 
									
										
										
										
											2021-01-14 09:15:32 +01:00
										 |  |  |                 builder.append("))"); | 
					
						
							| 
									
										
										
										
											2019-08-03 16:35:49 +02:00
										 |  |  |                 if (i != parameters.size() - 1) | 
					
						
							|  |  |  |                     builder.append(", "); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             builder.append(" {}"); | 
					
						
							|  |  |  |             return builder.to_string(); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-23 16:43:21 +01:00
										 |  |  |         auto do_message = [&](const String& name, const Vector<Parameter>& parameters, const String& response_type = {}) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |             auto message_generator = endpoint_generator.fork(); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |             auto pascal_name = pascal_case(name); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |             message_generator.set("message.name", name); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |             message_generator.set("message.pascal_name", pascal_name); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |             message_generator.set("message.response_type", response_type); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |             message_generator.set("message.constructor", constructor_for_message(pascal_name, parameters)); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  | class @message.pascal_name@ final : public IPC::Message { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | public: | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 16:05:53 +02:00
										 |  |  |             if (!response_type.is_null()) | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 message_generator.append(R"~~~( | 
					
						
							|  |  |  |    typedef class @message.response_type@ ResponseType; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |     @message.pascal_name@(decltype(nullptr)) : m_ipc_message_valid(false) { } | 
					
						
							|  |  |  |     @message.pascal_name@(@message.pascal_name@ const&) = default; | 
					
						
							|  |  |  |     @message.pascal_name@(@message.pascal_name@&&) = default; | 
					
						
							|  |  |  |     @message.pascal_name@& operator=(@message.pascal_name@ const&) = default; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |     @message.constructor@ | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |     virtual ~@message.pascal_name@() override {} | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 13:19:53 +02:00
										 |  |  |     virtual u32 endpoint_magic() const override { return @endpoint.magic@; } | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |     virtual i32 message_id() const override { return (int)MessageID::@message.pascal_name@; } | 
					
						
							|  |  |  |     static i32 static_message_id() { return (int)MessageID::@message.pascal_name@; } | 
					
						
							|  |  |  |     virtual const char* message_name() const override { return "@endpoint.name@::@message.pascal_name@"; } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 17:00:38 +02:00
										 |  |  |     static OwnPtr<@message.pascal_name@> decode(InputMemoryStream& stream, [[maybe_unused]] int sockfd) | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-11-21 21:59:12 +03:00
										 |  |  |         IPC::Decoder decoder { stream, sockfd }; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             for (auto& parameter : parameters) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |                 auto parameter_generator = message_generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 parameter_generator.set("parameter.type", parameter.type); | 
					
						
							|  |  |  |                 parameter_generator.set("parameter.name", parameter.name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 17:24:47 +02:00
										 |  |  |                 if (parameter.type == "bool") | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                     parameter_generator.set("parameter.initial_value", "false"); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     parameter_generator.set("parameter.initial_value", "{}"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 parameter_generator.append(R"~~~( | 
					
						
							|  |  |  |         @parameter.type@ @parameter.name@ = @parameter.initial_value@; | 
					
						
							|  |  |  |         if (!decoder.decode(@parameter.name@)) | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-16 14:11:35 +02:00
										 |  |  |                 if (parameter.attributes.contains_slow("UTF8")) { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                     parameter_generator.append(R"~~~( | 
					
						
							|  |  |  |         if (!Utf8View(@parameter.name@).validate()) | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2020-05-16 14:11:35 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             StringBuilder builder; | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |             for (size_t i = 0; i < parameters.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |                 auto& parameter = parameters[i]; | 
					
						
							| 
									
										
										
										
											2021-01-14 09:15:32 +01:00
										 |  |  |                 builder.append("move("); | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |                 builder.append(parameter.name); | 
					
						
							| 
									
										
										
										
											2021-01-14 09:15:32 +01:00
										 |  |  |                 builder.append(")"); | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |                 if (i != parameters.size() - 1) | 
					
						
							|  |  |  |                     builder.append(", "); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             message_generator.set("message.constructor_call_parameters", builder.build()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |         return make<@message.pascal_name@>(@message.constructor_call_parameters@); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-02 05:20:28 +02:00
										 |  |  |     virtual bool valid() const { return m_ipc_message_valid; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |     virtual IPC::MessageBuffer encode() const override | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-05-02 05:20:28 +02:00
										 |  |  |         VERIFY(valid()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         IPC::MessageBuffer buffer; | 
					
						
							|  |  |  |         IPC::Encoder stream(buffer); | 
					
						
							|  |  |  |         stream << endpoint_magic(); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |         stream << (int)MessageID::@message.pascal_name@; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 16:35:49 +02:00
										 |  |  |             for (auto& parameter : parameters) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |                 auto parameter_generator = message_generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 parameter_generator.set("parameter.name", parameter.name); | 
					
						
							|  |  |  |                 parameter_generator.append(R"~~~( | 
					
						
							|  |  |  |         stream << m_@parameter.name@; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             message_generator.append(R"~~~( | 
					
						
							|  |  |  |         return buffer; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 17:24:47 +02:00
										 |  |  |             for (auto& parameter : parameters) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |                 auto parameter_generator = message_generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 parameter_generator.set("parameter.type", parameter.type); | 
					
						
							|  |  |  |                 parameter_generator.set("parameter.name", parameter.name); | 
					
						
							|  |  |  |                 parameter_generator.append(R"~~~( | 
					
						
							|  |  |  |     const @parameter.type@& @parameter.name@() const { return m_@parameter.name@; } | 
					
						
							| 
									
										
										
										
											2021-06-13 08:20:27 +02:00
										 |  |  |     @parameter.type@ take_@parameter.name@() { return move(m_@parameter.name@); } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 17:24:47 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             message_generator.append(R"~~~( | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-05-02 04:39:36 +02:00
										 |  |  |     bool m_ipc_message_valid { true }; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |             )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |             for (auto& parameter : parameters) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |                 auto parameter_generator = message_generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 parameter_generator.set("parameter.type", parameter.type); | 
					
						
							|  |  |  |                 parameter_generator.set("parameter.name", parameter.name); | 
					
						
							|  |  |  |                 parameter_generator.append(R"~~~( | 
					
						
							|  |  |  |     @parameter.type@ m_@parameter.name@; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             message_generator.append(R"~~~( | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  |             )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |         }; | 
					
						
							|  |  |  |         for (auto& message : endpoint.messages) { | 
					
						
							| 
									
										
										
										
											2019-08-03 16:05:53 +02:00
										 |  |  |             String response_name; | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |             if (message.is_synchronous) { | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |                 response_name = message.response_name(); | 
					
						
							| 
									
										
										
										
											2019-08-03 16:05:53 +02:00
										 |  |  |                 do_message(response_name, message.outputs); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-08-03 16:05:53 +02:00
										 |  |  |             do_message(message.name, message.inputs, response_name); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  | } // namespace Messages::@endpoint.name@
 | 
					
						
							|  |  |  |         )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | template<typename LocalEndpoint, typename PeerEndpoint> | 
					
						
							|  |  |  | class @endpoint.name@Proxy { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |     // Used to disambiguate the constructor call.
 | 
					
						
							|  |  |  |     struct Tag { }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @endpoint.name@Proxy(IPC::Connection<LocalEndpoint, PeerEndpoint>& connection, Tag) | 
					
						
							|  |  |  |         : m_connection(connection) | 
					
						
							|  |  |  |     { } | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (auto& message : endpoint.messages) { | 
					
						
							|  |  |  |             auto message_generator = endpoint_generator.fork(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |             auto do_implement_proxy = [&](String const& name, Vector<Parameter> const& parameters, bool is_synchronous, bool is_try) { | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                 String return_type = "void"; | 
					
						
							| 
									
										
										
										
											2021-05-03 13:55:29 +02:00
										 |  |  |                 if (is_synchronous) { | 
					
						
							|  |  |  |                     if (message.outputs.size() == 1) | 
					
						
							|  |  |  |                         return_type = message.outputs[0].type; | 
					
						
							|  |  |  |                     else if (!message.outputs.is_empty()) | 
					
						
							|  |  |  |                         return_type = message_name(endpoint.name, message.name, true); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |                 String inner_return_type = return_type; | 
					
						
							|  |  |  |                 if (is_try) { | 
					
						
							|  |  |  |                     StringBuilder builder; | 
					
						
							|  |  |  |                     builder.append("Result<"); | 
					
						
							|  |  |  |                     builder.append(return_type); | 
					
						
							|  |  |  |                     builder.append(", IPC::ErrorCode>"); | 
					
						
							|  |  |  |                     return_type = builder.to_string(); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                 message_generator.set("message.name", message.name); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |                 message_generator.set("message.pascal_name", pascal_case(message.name)); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                 message_generator.set("message.complex_return_type", return_type); | 
					
						
							|  |  |  |                 message_generator.set("async_prefix_maybe", is_synchronous ? "" : "async_"); | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |                 message_generator.set("try_prefix_maybe", is_try ? "try_" : ""); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |                 message_generator.set("handler_name", name); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                 message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |     @message.complex_return_type@ @try_prefix_maybe@@async_prefix_maybe@@handler_name@()~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 for (size_t i = 0; i < parameters.size(); ++i) { | 
					
						
							|  |  |  |                     auto& parameter = parameters[i]; | 
					
						
							|  |  |  |                     auto argument_generator = message_generator.fork(); | 
					
						
							|  |  |  |                     argument_generator.set("argument.type", parameter.type); | 
					
						
							|  |  |  |                     argument_generator.set("argument.name", parameter.name); | 
					
						
							|  |  |  |                     argument_generator.append("@argument.type@ @argument.name@"); | 
					
						
							|  |  |  |                     if (i != parameters.size() - 1) | 
					
						
							|  |  |  |                         argument_generator.append(", "); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 message_generator.append(") {"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |                 if (is_synchronous && !is_try) { | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                     if (return_type != "void") { | 
					
						
							|  |  |  |                         message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 13:55:29 +02:00
										 |  |  |         return )~~~"); | 
					
						
							|  |  |  |                         if (message.outputs.size() != 1) | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |                             message_generator.append("move(*"); | 
					
						
							| 
									
										
										
										
											2021-05-03 13:55:29 +02:00
										 |  |  |                     } else { | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                         message_generator.append(R"~~~( | 
					
						
							|  |  |  |         )~~~"); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |                     message_generator.append("m_connection.template send_sync<Messages::@endpoint.name@::@message.pascal_name@>("); | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |                 } else if (is_try) { | 
					
						
							|  |  |  |                     message_generator.append(R"~~~( | 
					
						
							|  |  |  |         auto result = m_connection.template send_sync_but_allow_failure<Messages::@endpoint.name@::@message.pascal_name@>()~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                 } else { | 
					
						
							|  |  |  |                     message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |         m_connection.post_message(Messages::@endpoint.name@::@message.pascal_name@ { )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (size_t i = 0; i < parameters.size(); ++i) { | 
					
						
							|  |  |  |                     auto& parameter = parameters[i]; | 
					
						
							|  |  |  |                     auto argument_generator = message_generator.fork(); | 
					
						
							|  |  |  |                     argument_generator.set("argument.name", parameter.name); | 
					
						
							|  |  |  |                     if (is_primitive_type(parameters[i].type)) | 
					
						
							|  |  |  |                         argument_generator.append("@argument.name@"); | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                         argument_generator.append("move(@argument.name@)"); | 
					
						
							|  |  |  |                     if (i != parameters.size() - 1) | 
					
						
							|  |  |  |                         argument_generator.append(", "); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |                 if (is_synchronous && !is_try) { | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                     if (return_type != "void") { | 
					
						
							|  |  |  |                         message_generator.append(")"); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 13:55:29 +02:00
										 |  |  |                     if (message.outputs.size() == 1) { | 
					
						
							| 
									
										
										
										
											2021-06-13 08:20:27 +02:00
										 |  |  |                         message_generator.append("->take_"); | 
					
						
							| 
									
										
										
										
											2021-05-03 13:55:29 +02:00
										 |  |  |                         message_generator.append(message.outputs[0].name); | 
					
						
							|  |  |  |                         message_generator.append("()"); | 
					
						
							|  |  |  |                     } else | 
					
						
							|  |  |  |                         message_generator.append(")"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |                     message_generator.append(";"); | 
					
						
							|  |  |  |                 } else if (is_try) { | 
					
						
							|  |  |  |                     message_generator.append(R"~~~(); | 
					
						
							|  |  |  |         if (!result) | 
					
						
							|  |  |  |             return IPC::ErrorCode::PeerDisconnected; | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |                     if (inner_return_type != "void") { | 
					
						
							|  |  |  |                         message_generator.append(R"~~~( | 
					
						
							|  |  |  |         return move(*result); | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         message_generator.append(R"~~~( | 
					
						
							|  |  |  |         return { }; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                 } else { | 
					
						
							|  |  |  |                     message_generator.append(R"~~~( }); | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 message_generator.append(R"~~~( | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |             }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 16:51:42 +02:00
										 |  |  |             do_implement_proxy(message.name, message.inputs, message.is_synchronous, false); | 
					
						
							|  |  |  |             if (message.is_synchronous) { | 
					
						
							|  |  |  |                 do_implement_proxy(message.name, message.inputs, false, false); | 
					
						
							|  |  |  |                 do_implement_proxy(message.name, message.inputs, true, true); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     IPC::Connection<LocalEndpoint, PeerEndpoint>& m_connection; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  | template<typename LocalEndpoint, typename PeerEndpoint> | 
					
						
							|  |  |  | class @endpoint.name@Proxy; | 
					
						
							|  |  |  | class @endpoint.name@Stub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class @endpoint.name@Endpoint { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     template<typename LocalEndpoint> | 
					
						
							|  |  |  |     using Proxy = @endpoint.name@Proxy<LocalEndpoint, @endpoint.name@Endpoint>; | 
					
						
							|  |  |  |     using Stub = @endpoint.name@Stub; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 13:19:53 +02:00
										 |  |  |     static u32 static_magic() { return @endpoint.magic@; } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 17:00:38 +02:00
										 |  |  |     static OwnPtr<IPC::Message> decode_message(ReadonlyBytes buffer, [[maybe_unused]] int sockfd) | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         InputMemoryStream stream { buffer }; | 
					
						
							| 
									
										
										
										
											2021-04-25 13:19:53 +02:00
										 |  |  |         u32 message_endpoint_magic = 0; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         stream >> message_endpoint_magic; | 
					
						
							|  |  |  |         if (stream.handle_any_error()) { | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         if constexpr (GENERATE_DEBUG_CODE) { | 
					
						
							|  |  |  |             endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  |                 dbgln("Failed to read message endpoint magic"); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (message_endpoint_magic != @endpoint.magic@) { | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         if constexpr (GENERATE_DEBUG_CODE) { | 
					
						
							|  |  |  |             endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  |                 dbgln("@endpoint.name@: Endpoint magic number message_endpoint_magic != @endpoint.magic@, not my message! (the other endpoint may have handled it)"); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         i32 message_id = 0; | 
					
						
							|  |  |  |         stream >> message_id; | 
					
						
							|  |  |  |         if (stream.handle_any_error()) { | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         if constexpr (GENERATE_DEBUG_CODE) { | 
					
						
							|  |  |  |             endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  |                 dbgln("Failed to read message ID"); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         OwnPtr<IPC::Message> message; | 
					
						
							|  |  |  |         switch (message_id) { | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |         for (auto& message : endpoint.messages) { | 
					
						
							|  |  |  |             auto do_decode_message = [&](const String& name) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |                 auto message_generator = endpoint_generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 message_generator.set("message.name", name); | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |                 message_generator.set("message.pascal_name", pascal_case(name)); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |         case (int)Messages::@endpoint.name@::MessageID::@message.pascal_name@: | 
					
						
							|  |  |  |             message = Messages::@endpoint.name@::@message.pascal_name@::decode(stream, sockfd); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |             break; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |             }; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 17:03:16 +02:00
										 |  |  |             do_decode_message(message.name); | 
					
						
							|  |  |  |             if (message.is_synchronous) | 
					
						
							|  |  |  |                 do_decode_message(message.response_name()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         if constexpr (GENERATE_DEBUG_CODE) { | 
					
						
							|  |  |  |             endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  |                 dbgln("Failed to decode @endpoint.name@.({})", message_id); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-04-06 10:12:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         if (stream.handle_any_error()) { | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         if constexpr (GENERATE_DEBUG_CODE) { | 
					
						
							|  |  |  |             endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  |                 dbgln("Failed to read the message"); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return message; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class @endpoint.name@Stub : public IPC::Stub { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     @endpoint.name@Stub() { } | 
					
						
							|  |  |  |     virtual ~@endpoint.name@Stub() override { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual u32 magic() const override { return @endpoint.magic@; } | 
					
						
							|  |  |  |     virtual String name() const override { return "@endpoint.name@"; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-02 04:39:36 +02:00
										 |  |  |     virtual OwnPtr<IPC::MessageBuffer> handle(const IPC::Message& message) override | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         switch (message.message_id()) { | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 19:21:15 +02:00
										 |  |  |         for (auto& message : endpoint.messages) { | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |             auto do_handle_message = [&](String const& name, Vector<Parameter> const& parameters, bool returns_something) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |                 auto message_generator = endpoint_generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |                 StringBuilder argument_generator; | 
					
						
							|  |  |  |                 for (size_t i = 0; i < parameters.size(); ++i) { | 
					
						
							|  |  |  |                     auto& parameter = parameters[i]; | 
					
						
							|  |  |  |                     argument_generator.append("request."); | 
					
						
							|  |  |  |                     argument_generator.append(parameter.name); | 
					
						
							|  |  |  |                     argument_generator.append("()"); | 
					
						
							|  |  |  |                     if (i != parameters.size() - 1) | 
					
						
							|  |  |  |                         argument_generator.append(", "); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |                 message_generator.set("message.pascal_name", pascal_case(name)); | 
					
						
							|  |  |  |                 message_generator.set("message.response_type", pascal_case(message.response_name())); | 
					
						
							|  |  |  |                 message_generator.set("handler_name", name); | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |                 message_generator.set("arguments", argument_generator.to_string()); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |         case (int)Messages::@endpoint.name@::MessageID::@message.pascal_name@: { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 19:21:15 +02:00
										 |  |  |                 if (returns_something) { | 
					
						
							| 
									
										
										
										
											2021-05-02 05:20:28 +02:00
										 |  |  |                     if (message.outputs.is_empty()) { | 
					
						
							|  |  |  |                         message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |             [[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.pascal_name@&>(message); | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |             @handler_name@(@arguments@); | 
					
						
							| 
									
										
										
										
											2021-05-02 05:20:28 +02:00
										 |  |  |             auto response = Messages::@endpoint.name@::@message.response_type@ { }; | 
					
						
							|  |  |  |             return make<IPC::MessageBuffer>(response.encode()); | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |             [[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.pascal_name@&>(message); | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |             auto response = @handler_name@(@arguments@); | 
					
						
							| 
									
										
										
										
											2021-05-02 05:20:28 +02:00
										 |  |  |             if (!response.valid()) | 
					
						
							|  |  |  |                 return {}; | 
					
						
							| 
									
										
										
										
											2021-05-02 04:39:36 +02:00
										 |  |  |             return make<IPC::MessageBuffer>(response.encode()); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-02 05:20:28 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2019-08-03 19:21:15 +02:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                     message_generator.append(R"~~~( | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |             [[maybe_unused]] auto& request = static_cast<const Messages::@endpoint.name@::@message.pascal_name@&>(message); | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |             @handler_name@(@arguments@); | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 19:21:15 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-05-02 05:20:28 +02:00
										 |  |  |                 message_generator.append(R"~~~( | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 19:21:15 +02:00
										 |  |  |             }; | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |             do_handle_message(message.name, message.inputs, message.is_synchronous); | 
					
						
							| 
									
										
										
										
											2019-08-03 19:21:15 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  |         default: | 
					
						
							| 
									
										
										
										
											2021-01-10 16:29:28 -07:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (auto& message : endpoint.messages) { | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |             auto message_generator = endpoint_generator.fork(); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |             auto do_handle_message_decl = [&](String const& name, Vector<Parameter> const& parameters, bool is_response) { | 
					
						
							|  |  |  |                 String return_type = "void"; | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                 if (message.is_synchronous && !message.outputs.is_empty() && !is_response) | 
					
						
							|  |  |  |                     return_type = message_name(endpoint.name, message.name, true); | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |                 message_generator.set("message.complex_return_type", return_type); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 15:52:56 +02:00
										 |  |  |                 message_generator.set("handler_name", name); | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |                 message_generator.append(R"~~~( | 
					
						
							|  |  |  |     virtual @message.complex_return_type@ @handler_name@()~~~"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 auto make_argument_type = [](String const& type) { | 
					
						
							|  |  |  |                     StringBuilder builder; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-03 08:46:40 +02:00
										 |  |  |                     bool const_ref = !is_primitive_type(type); | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     builder.append(type); | 
					
						
							|  |  |  |                     if (const_ref) | 
					
						
							|  |  |  |                         builder.append(" const&"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     return builder.to_string(); | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (size_t i = 0; i < parameters.size(); ++i) { | 
					
						
							|  |  |  |                     auto& parameter = parameters[i]; | 
					
						
							|  |  |  |                     auto argument_generator = message_generator.fork(); | 
					
						
							|  |  |  |                     argument_generator.set("argument.type", make_argument_type(parameter.type)); | 
					
						
							|  |  |  |                     argument_generator.set("argument.name", parameter.name); | 
					
						
							|  |  |  |                     argument_generator.append("[[maybe_unused]] @argument.type@ @argument.name@"); | 
					
						
							|  |  |  |                     if (i != parameters.size() - 1) | 
					
						
							|  |  |  |                         argument_generator.append(", "); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |                 if (is_response) { | 
					
						
							|  |  |  |                     message_generator.append(R"~~~() { }; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     message_generator.append(R"~~~() = 0; | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2021-05-02 19:54:34 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             do_handle_message_decl(message.name, message.inputs, false); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         endpoint_generator.append(R"~~~( | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | )~~~"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-23 18:36:56 +02:00
										 |  |  |     outln("{}", generator.as_string_view()); | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |     for (auto& endpoint : endpoints) { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |         warnln("Endpoint '{}' (magic: {})", endpoint.name, endpoint.magic); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |         for (auto& message : endpoint.messages) { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |             warnln("  Message: '{}'", message.name); | 
					
						
							|  |  |  |             warnln("    Sync: {}", message.is_synchronous); | 
					
						
							|  |  |  |             warnln("    Inputs:"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |             for (auto& parameter : message.inputs) | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 warnln("      Parameter: {} ({})", parameter.name, parameter.type); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |             if (message.inputs.is_empty()) | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 warnln("      (none)"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |             if (message.is_synchronous) { | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                 warnln("    Outputs:"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |                 for (auto& parameter : message.outputs) | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                     warnln("      Parameter: {} ({})", parameter.name, parameter.type); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |                 if (message.outputs.is_empty()) | 
					
						
							| 
									
										
										
										
											2020-10-11 19:57:53 +02:00
										 |  |  |                     warnln("      (none)"); | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-08-03 15:50:16 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-08-03 15:15:11 +02:00
										 |  |  | } |