| 428 | } |
| 429 | |
| 430 | void validate(const File& file) { |
| 431 | std::unordered_set<std::string> typeNames; |
| 432 | for (const auto& decl : file.enums) ensureUnique(typeNames, decl.name, "type", decl.line); |
| 433 | for (const auto& decl : file.structs) ensureUnique(typeNames, decl.name, "type", decl.line); |
| 434 | |
| 435 | std::unordered_set<std::string> protocolNames; |
| 436 | for (const auto& decl : file.protocols) |
| 437 | ensureUnique(protocolNames, decl.name, "protocol", decl.line); |
| 438 | |
| 439 | std::unordered_set<std::string> interfaceNames; |
| 440 | for (const auto& iface : file.interfaces) |
| 441 | ensureUnique(interfaceNames, iface.name, "interface", iface.line); |
| 442 | |
| 443 | const EnumDecl* interfaceEnum = findEnum(file, "EIPCInterface"); |
| 444 | if (!interfaceEnum) fail("missing EIPCInterface enum"); |
| 445 | std::unordered_set<std::string> interfaceMembers; |
| 446 | for (const auto& member : interfaceEnum->members) interfaceMembers.insert(member.name); |
| 447 | for (const auto& iface : file.interfaces) { |
| 448 | if (!interfaceMembers.contains(iface.name)) |
| 449 | fail(iface.line, "interface '" + iface.name + "' has no EIPCInterface member"); |
| 450 | for (const auto& method : iface.methods) validateMethod(method); |
| 451 | } |
| 452 | |
| 453 | if (file.protocols.size() != 1 || file.protocols.front().name != "IPC") |
| 454 | fail("exactly one 'protocol IPC' declaration is required"); |
| 455 | const ProtocolDecl& protocol = file.protocols.front(); |
| 456 | if (!findStruct(file, protocol.requestHeader)) |
| 457 | fail(protocol.line, "unknown protocol request header '" + protocol.requestHeader + "'"); |
| 458 | |
| 459 | const CommandDecl* interfaceCall = nullptr; |
| 460 | for (const auto& command : protocol.commands) { |
| 461 | validateFrame(file, command.request, "request"); |
| 462 | if (!command.responseNone) validateFrame(file, command.response, "response"); |
| 463 | if (command.name == "IPCInterfaceCall") interfaceCall = &command; |
| 464 | } |
| 465 | if (!interfaceCall) fail("protocol IPC must declare IPCInterfaceCall command"); |
| 466 | validateIPCInterfaceCall(*interfaceCall, file); |
| 467 | } |
| 468 | |
| 469 | void validateIPCInterfaceCall(const CommandDecl& command, const File& file) { |
| 470 | if (command.enumValue != "EIPCCommand::InterfaceCall") |