UCIEndpoint.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "UCIEndpoint.h"
  7. #include <AK/ByteBuffer.h>
  8. #include <AK/Debug.h>
  9. #include <AK/DeprecatedString.h>
  10. #include <LibCore/EventLoop.h>
  11. namespace Chess::UCI {
  12. Endpoint::Endpoint(NonnullRefPtr<Core::IODevice> in, NonnullRefPtr<Core::IODevice> out)
  13. : m_in(in)
  14. , m_out(out)
  15. , m_in_notifier(Core::Notifier::construct(in->fd(), Core::Notifier::Read))
  16. {
  17. set_in_notifier();
  18. }
  19. void Endpoint::send_command(Command const& command)
  20. {
  21. dbgln_if(UCI_DEBUG, "{} Sent UCI Command: {}", class_name(), DeprecatedString(command.to_deprecated_string().characters(), Chomp));
  22. m_out->write(command.to_deprecated_string());
  23. }
  24. void Endpoint::event(Core::Event& event)
  25. {
  26. switch (static_cast<Command::Type>(event.type())) {
  27. case Command::Type::UCI:
  28. return handle_uci();
  29. case Command::Type::Debug:
  30. return handle_debug(static_cast<DebugCommand const&>(event));
  31. case Command::Type::IsReady:
  32. return handle_uci();
  33. case Command::Type::SetOption:
  34. return handle_setoption(static_cast<SetOptionCommand const&>(event));
  35. case Command::Type::Position:
  36. return handle_position(static_cast<PositionCommand const&>(event));
  37. case Command::Type::Go:
  38. return handle_go(static_cast<GoCommand const&>(event));
  39. case Command::Type::Stop:
  40. return handle_stop();
  41. case Command::Type::Id:
  42. return handle_id(static_cast<IdCommand const&>(event));
  43. case Command::Type::UCIOk:
  44. return handle_uciok();
  45. case Command::Type::ReadyOk:
  46. return handle_readyok();
  47. case Command::Type::BestMove:
  48. return handle_bestmove(static_cast<BestMoveCommand const&>(event));
  49. case Command::Type::Info:
  50. return handle_info(static_cast<InfoCommand const&>(event));
  51. case Command::Type::Quit:
  52. return handle_quit();
  53. default:
  54. Object::event(event);
  55. break;
  56. }
  57. }
  58. void Endpoint::custom_event(Core::CustomEvent& custom_event)
  59. {
  60. if (custom_event.custom_type() == EndpointEventType::UnexpectedEof)
  61. handle_unexpected_eof();
  62. }
  63. void Endpoint::set_in_notifier()
  64. {
  65. m_in_notifier = Core::Notifier::construct(m_in->fd(), Core::Notifier::Read);
  66. m_in_notifier->on_ready_to_read = [this] {
  67. if (!m_in->can_read_line()) {
  68. Core::EventLoop::current().post_event(*this, make<Core::CustomEvent>(EndpointEventType::UnexpectedEof));
  69. m_in_notifier->set_enabled(false);
  70. return;
  71. }
  72. while (m_in->can_read_line())
  73. Core::EventLoop::current().post_event(*this, read_command());
  74. };
  75. }
  76. NonnullOwnPtr<Command> Endpoint::read_command()
  77. {
  78. DeprecatedString line(ReadonlyBytes(m_in->read_line(4096).bytes()), Chomp);
  79. dbgln_if(UCI_DEBUG, "{} Received UCI Command: {}", class_name(), line);
  80. if (line == "uci") {
  81. return make<UCICommand>(UCICommand::from_string(line));
  82. } else if (line.starts_with("debug"sv)) {
  83. return make<DebugCommand>(DebugCommand::from_string(line));
  84. } else if (line.starts_with("isready"sv)) {
  85. return make<IsReadyCommand>(IsReadyCommand::from_string(line));
  86. } else if (line.starts_with("setoption"sv)) {
  87. return make<SetOptionCommand>(SetOptionCommand::from_string(line));
  88. } else if (line.starts_with("position"sv)) {
  89. return make<PositionCommand>(PositionCommand::from_string(line));
  90. } else if (line.starts_with("go"sv)) {
  91. return make<GoCommand>(GoCommand::from_string(line));
  92. } else if (line.starts_with("stop"sv)) {
  93. return make<StopCommand>(StopCommand::from_string(line));
  94. } else if (line.starts_with("id"sv)) {
  95. return make<IdCommand>(IdCommand::from_string(line));
  96. } else if (line.starts_with("uciok"sv)) {
  97. return make<UCIOkCommand>(UCIOkCommand::from_string(line));
  98. } else if (line.starts_with("readyok"sv)) {
  99. return make<ReadyOkCommand>(ReadyOkCommand::from_string(line));
  100. } else if (line.starts_with("bestmove"sv)) {
  101. return make<BestMoveCommand>(BestMoveCommand::from_string(line));
  102. } else if (line.starts_with("info"sv)) {
  103. return make<InfoCommand>(InfoCommand::from_string(line));
  104. } else if (line.starts_with("quit"sv)) {
  105. return make<QuitCommand>(QuitCommand::from_string(line));
  106. }
  107. dbgln("command line: {}", line);
  108. VERIFY_NOT_REACHED();
  109. }
  110. };