use crate::interface::args::Cli;
use clap::Parser;
use reqwest::{header::CONTENT_TYPE, Client};
use serde::{Deserialize, Serialize};
use spinoff::{spinners, Color, Spinner};
const PLAYGROUND_URL: &str = "https://play.rust-lang.org/execute";
#[allow(non_snake_case)]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct RequestPayload {
channel: String,
mode: String,
edition: String,
crateType: String,
tests: bool,
backtrace: bool,
code: String,
}
#[derive(Debug, Deserialize)]
struct ResponsePayload {
stdout: Option<String>,
stderr: Option<String>,
}
impl RequestPayload {
fn new(code: &str) -> RequestPayload {
let cli = Cli::parse();
RequestPayload {
channel: cli.channel,
mode: cli.mode,
edition: cli.edition,
crateType: "bin".to_string(),
tests: cli.tests,
backtrace: cli.backtrace,
code: code.to_string(),
}
}
}
pub async fn run_rustycli() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
let filename = &cli.run;
let raw_code = tokio::fs::read_to_string(filename).await?;
let spinner = Spinner::new(spinners::Dots, "Compiling... ", Color::Green);
let code = raw_code.trim();
let request_payload = RequestPayload::new(code);
let client = Client::new();
let request_builder = client
.post(PLAYGROUND_URL)
.header(CONTENT_TYPE, "application/json")
.json(&request_payload);
let resp_json = request_builder
.send()
.await?
.json::<ResponsePayload>()
.await?;
let match_result = match (resp_json.stdout, resp_json.stderr) {
(Some(stdout), _) if !stdout.is_empty() => stdout,
(_, Some(stderr)) => stderr,
_ => String::from("Error: No stdout or stderr found in the response."),
};
spinner.success(&match_result);
Ok(())
}