/* * This source code is released into the public domain. */ module; #include #include #include #include #include #include #include #include #include module liblfvm; import nihil; namespace lfvm { /* * Split an option into name and value. */ [[nodiscard]] auto parse_option(std::string_view str) -> std::expected, nihil::error> { auto split = std::ranges::find(str, '='); if (split == str.end()) return std::unexpected(nihil::error( "missing '=' in option string")); auto option = std::string_view(str.begin(), split); if (option.empty()) return std::unexpected(nihil::error( "invalid option name")); auto value = std::string_view(std::next(split), str.end()); if (value.empty()) return std::unexpected(nihil::error( "invalid option value")); return std::make_pair(option, value); } /* * Parse a boolean option (true/false). */ [[nodiscard]] auto parse_bool(std::string_view value) -> std::expected { using namespace std::literals; static auto true_values = std::unordered_set{ "yes"sv, "true"sv, "enabled"sv, "on"sv }; static auto false_values = std::unordered_set{ "no"sv, "false"sv, "disabled"sv, "off"sv }; if (true_values.find(value) != true_values.end()) return true; if (false_values.find(value) != false_values.end()) return false; return std::unexpected(nihil::error("invalid value for boolean")); } auto set_vm_option(vm_config &vm, std::string_view option_string) -> std::expected { using namespace std::literals; // The table of options we know how to set. static auto options = std::unordered_map< std::string_view, std::function< std::expected( vm_config &, std::string_view) > > { std::make_pair("memory"sv, [](vm_config &vm, std::string_view str) -> std::expected { // Due to limitations in UCL, the memory size is limited to // int64_t. In practice, this is not an issue. auto new_size = co_await nihil::parse_size(str); co_await vm.memory_size(new_size); co_return {}; }), std::make_pair("ncpus"sv, [](vm_config &vm, std::string_view str) -> std::expected { auto ncpus = co_await nihil::parse_size(str); co_await vm.ncpus(ncpus); co_return {}; }), std::make_pair("wire_memory"sv, [](vm_config &vm, std::string_view str) -> std::expected { auto b = co_await parse_bool(str); vm.wire_memory(b); co_return {}; }), std::make_pair("include_memory_in_core"sv, [](vm_config &vm, std::string_view str) -> std::expected { auto b = co_await parse_bool(str); vm.include_memory_in_core(b); co_return {}; }), }; auto [name, value] = co_await parse_option(option_string); auto option = options.find(name); if (option == options.end()) co_return std::unexpected(nihil::error( std::format("unknown option '{}'", name))); co_await option->second(vm, value).transform_error( [&](nihil::error cause) { return nihil::error( std::format("failed to set {}", name), std::move(cause)); }); co_return {}; } } // namespace lfvm