Skip to content

Commit

Permalink
Split code CLI options (lib) from setting C++ flags (wrapper).
Browse files Browse the repository at this point in the history
  • Loading branch information
lgarron committed Aug 24, 2023
1 parent 9af5f6b commit 7b89b1d
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 221 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/cpp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rouille = "3.6.2"
serde = { version = "1.0.160", features = ["derive", "rc"] }
serde_json = "1.0.96"
tempfile = "3.5.0"
twsearch = { path = "../rs" }

[dev-dependencies]
wait-timeout = "0.2.0"
Expand Down
21 changes: 10 additions & 11 deletions src/cpp/rs/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
mod options;
mod search;
mod serialize;
mod serve;
mod wrapper_options;

use std::process::exit;

use search::main_search;
use serve::serve;

use crate::options::get_options;
use twsearch::_internal::cli::{get_options_cpp_wrapper, CliCommand};

// TODO: Figure out how to move this out of the main entry file.
#[cxx::bridge]
Expand All @@ -27,13 +26,13 @@ pub mod rust_api {
}

fn main() {
let args = get_options();
let args = get_options_cpp_wrapper();

let result = match args.command {
options::Command::Completions(_completions_args) => {
CliCommand::Completions(_completions_args) => {
panic!("Completions should have been printed during options parsing, followed by program exit.");
}
options::Command::Search(search_command_args) => main_search(
CliCommand::Search(search_command_args) => main_search(
&search_command_args,
&search_command_args
.input_args
Expand All @@ -46,9 +45,9 @@ fn main() {
.debug_print_serialized_json,
&search_command_args.input_args.experimental_target_pattern,
),
options::Command::Serve(serve_command_args) => serve(serve_command_args),
CliCommand::Serve(serve_command_args) => serve(serve_command_args, true),
// TODO: consolidate def-only arg implementations.
options::Command::SchreierSims(schreier_sims_command_args) => {
CliCommand::SchreierSims(schreier_sims_command_args) => {
println!("Warning: `schreier-sims` does not support searching with identical pieces. If there are any identical pieces, they will be treated as distinguishable.");

main_search(
Expand All @@ -61,21 +60,21 @@ fn main() {
&None, // TODO: allow custom target pattern?
)
}
options::Command::GodsAlgorithm(gods_algorithm_args) => main_search(
CliCommand::GodsAlgorithm(gods_algorithm_args) => main_search(
&gods_algorithm_args,
&gods_algorithm_args.input_args.def_file,
&None,
gods_algorithm_args.input_args.debug_print_serialized_json,
&None, // TODO: allow custom target pattern?
),
options::Command::TimingTest(args) => main_search(
CliCommand::TimingTest(args) => main_search(
&args,
&args.input_args.def_file,
&None,
args.input_args.debug_print_serialized_json,
&None, // TODO: allow custom target pattern?
),
options::Command::CanonicalAlgs(args) => main_search(
CliCommand::CanonicalAlgs(args) => main_search(
&args,
&args.input_args.def_file,
&None,
Expand Down
2 changes: 1 addition & 1 deletion src/cpp/rs/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use serde::Deserialize;
use tempfile::NamedTempFile;

use crate::{
options::{reset_args_from, SetCppArgs},
rust_api,
serialize::{
serialize_kpuzzle_definition, serialize_scramble_list, serialize_scramble_state_data,
KPuzzleSerializationOptions, ScrambleList,
},
wrapper_options::{reset_args_from, SetCppArgs},
};

fn read_to_json<T: for<'a> Deserialize<'a>>(input_file: &Path) -> Result<T, String> {
Expand Down
15 changes: 8 additions & 7 deletions src/cpp/rs/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ use serde::Serialize;

use std::sync::Mutex;

use crate::options::reset_args_from;
use crate::wrapper_options::reset_args_from;

use crate::options::ServeArgsForIndividualSearch;
use crate::options::ServeClientArgs;
use crate::options::ServeCommandArgs;
use crate::rust_api;
use crate::serialize::serialize_kpuzzle_definition;
use crate::serialize::serialize_scramble_state_data;
use crate::serialize::KPuzzleSerializationOptions;
use twsearch::_internal::cli::ServeArgsForIndividualSearch;
use twsearch::_internal::cli::ServeClientArgs;
use twsearch::_internal::cli::ServeCommandArgs;

fn set_definition(
def: KPuzzleDefinition,
Expand Down Expand Up @@ -92,15 +92,16 @@ fn cors(response: Response) -> Response {
.with_additional_header("Access-Control-Allow-Headers", "Content-Type")
}

pub fn serve(serve_command_args: ServeCommandArgs) -> Result<(), String> {
pub fn serve(serve_command_args: ServeCommandArgs, from_cpp_wrapper: bool) -> Result<(), String> {
let solve_mutex = Mutex::new(());
println!(
"Starting `twsearch-cpp-wrapper serve` on port 2023.
"Starting `twsearch{} serve` on port 2023.
Use with one of the following:
- https://experiments.cubing.net/cubing.js/twsearch/text-ui.html
- http://localhost:3333/experiments.cubing.net/cubing.js/twsearch/text-ui.html
"
",
if from_cpp_wrapper { "-cpp-wrapper" } else { "" }
);
rouille::start_server("0.0.0.0:2023", move |request: &Request| {
println!("Request: {} {}", request.method(), request.url()); // TODO: debug flag
Expand Down
211 changes: 211 additions & 0 deletions src/cpp/rs/wrapper_options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
use twsearch::_internal::cli::{
CanonicalAlgsArgs, CommonSearchArgs, EnableAutoAlwaysNeverValueEnum, GodsAlgorithmArgs,
InputDefAndOptionalScrambleFileArgs, MetricArgs, MovesArgs, PerformanceArgs, SchreierSimsArgs,
SearchCommandArgs, SearchPersistenceArgs, ServeArgsForIndividualSearch, ServeClientArgs,
ServeCommandArgs, TimingTestArgs,
};

use std::fmt::Display;

use cubing::alg::{Alg, Move};

use crate::rust_api;

fn is_enabled_with_default_true(v: &Option<EnableAutoAlwaysNeverValueEnum>) -> bool {
v.as_ref()
.unwrap_or(&EnableAutoAlwaysNeverValueEnum::Auto)
.enabled(|| true)
}

fn set_arg<T: Display>(arg_flag: &str, arg: &T) {
rust_api::rust_api_set_arg(&format!("{} {}", arg_flag, arg));
}

fn set_boolean_arg(arg_flag: &str, arg: bool) {
if arg {
rust_api::rust_api_set_arg(arg_flag);
}
}

fn set_optional_arg<T: Display>(arg_flag: &str, arg: &Option<T>) {
if let Some(v) = arg {
rust_api::rust_api_set_arg(&format!("{} {}", arg_flag, v));
}
}

fn set_moves_arg(moves: &[Move]) {
// TODO: Squishing together moves into a comma-separated string
// isn't semantically fantastic. But the moves already passed
// validation, so this is not as risky as if we were passing strings directly from the client.
set_arg(
"--moves",
&moves
.iter()
.map(|m| m.to_string())
.collect::<Vec<String>>()
.join(","),
);
}

pub fn reset_args_from(arg_structs: Vec<&dyn SetCppArgs>) {
rust_api::rust_api_reset();
for arg_struct in arg_structs {
arg_struct.set_cpp_args();
}
}

pub trait SetCppArgs {
fn set_cpp_args(&self);
}

impl SetCppArgs for CommonSearchArgs {
fn set_cpp_args(&self) {
set_boolean_arg(
"--checkbeforesolve",
is_enabled_with_default_true(&self.check_before_solve),
);
set_boolean_arg("--randomstart", self.random_start);
set_optional_arg("--mindepth", &self.min_depth);
set_optional_arg("-m", &self.max_depth);
set_optional_arg("--startprunedepth", &self.start_prune_depth);
self.performance_args.set_cpp_args();
}
}

impl SetCppArgs for SearchCommandArgs {
fn set_cpp_args(&self) {
set_optional_arg("-c", &self.min_num_solutions);

self.moves_args.set_cpp_args();
self.search_args.set_cpp_args();
self.search_persistence_args.set_cpp_args();
self.input_args.set_cpp_args();
self.metric_args.set_cpp_args();
}
}

impl SetCppArgs for MovesArgs {
fn set_cpp_args(&self) {
if let Some(moves_parsed) = &self.moves_parsed() {
set_moves_arg(moves_parsed);
}
}
}

impl SetCppArgs for SearchPersistenceArgs {
fn set_cpp_args(&self) {
set_optional_arg("--writeprunetables", &self.write_prune_tables);
if let Some(cache_dir) = &self.cache_dir {
set_arg(
"--cachedir",
&cache_dir.to_str().expect("Invalid cache dir path."),
);
}
}
}

impl SetCppArgs for PerformanceArgs {
fn set_cpp_args(&self) {
let num_threads = match self.num_threads {
Some(num_threads) => num_threads,
None => num_cpus::get(),
};
println!("Setting twsearch to use {} threads.", num_threads);
rust_api::rust_api_set_arg(&format!("-t {}", num_threads));

set_optional_arg("-M", &self.memory_mebibytes);
}
}

impl SetCppArgs for SchreierSimsArgs {
fn set_cpp_args(&self) {
set_boolean_arg("--schreiersims", true);
self.performance_args.set_cpp_args();
}
}

impl SetCppArgs for GodsAlgorithmArgs {
fn set_cpp_args(&self) {
self.moves_args.set_cpp_args();
set_boolean_arg("-g", true);
set_boolean_arg("-F", self.force_arrays);
set_boolean_arg("-H", self.hash_states);
set_arg("-a", &self.num_antipodes);
self.performance_args.set_cpp_args();
self.metric_args.set_cpp_args();
}
}

impl SetCppArgs for TimingTestArgs {
fn set_cpp_args(&self) {
set_boolean_arg("-T", true);
self.performance_args.set_cpp_args();
self.metric_args.set_cpp_args();
}
}

impl SetCppArgs for CanonicalAlgsArgs {
fn set_cpp_args(&self) {
set_boolean_arg("-C", true);
self.performance_args.set_cpp_args();
self.metric_args.set_cpp_args();
}
}

impl SetCppArgs for MetricArgs {
fn set_cpp_args(&self) {
set_boolean_arg("-q", self.quantum_metric);
}
}

impl SetCppArgs for InputDefAndOptionalScrambleFileArgs {
fn set_cpp_args(&self) {
match &self.scramble_alg {
Some(scramble_alg) => {
let parsed_alg = match scramble_alg.parse::<Alg>() {
Ok(alg) => alg,
Err(_) => panic!("Invalid scramble alg."),
};
// TODO: Use `cubing::kpuzzle` to handle nested input syntax
set_arg("--scramblealg", &parsed_alg.to_string())
}
None => (),
};
set_boolean_arg("-s", self.stdin_scrambles)
}
}

impl SetCppArgs for ServeArgsForIndividualSearch<'_> {
fn set_cpp_args(&self) {
self.commandline_args.set_cpp_args();
// set_arg("-c", &"1000");
if let Some(client_args) = self.client_args {
client_args.set_cpp_args();
}
// Unconditional args
set_arg("--writeprunetables", &"never");
}
}

impl SetCppArgs for ServeCommandArgs {
fn set_cpp_args(&self) {
self.performance_args.set_cpp_args();
}
}

impl SetCppArgs for ServeClientArgs {
fn set_cpp_args(&self) {
set_boolean_arg(
"--checkbeforesolve",
is_enabled_with_default_true(&self.check_before_solve),
);
set_boolean_arg("--randomstart", self.random_start.unwrap_or(true));
set_optional_arg("--mindepth", &self.min_depth);
set_optional_arg("--maxdepth", &self.max_depth);
set_optional_arg("--startprunedepth", &self.start_prune_depth);
set_optional_arg("-q", &self.quantum_metric);
if let Some(move_subset) = &self.move_subset {
set_moves_arg(move_subset);
}
}
}
4 changes: 3 additions & 1 deletion src/rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ no_orientation_mod = []

[dependencies]
cityhash = "0.1.1"
clap = "4.3.24"
clap_complete = "4.3.2"
cubing = "0.5.4"
derive_more = "0.99.17"
serde = "1.0.186"

[dev-dependencies]
wait-timeout = "0.2.0"

[lib]
name = "twsearch"
path = "./mod.rs"
2 changes: 2 additions & 0 deletions src/rs/_internal/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod options;
pub use options::*;
Loading

0 comments on commit 7b89b1d

Please sign in to comment.