1use anyhow::{self, Context};
2use mini_async_repl::{
3 command::{
4 lift_validation_err, validate, ArgsError, Command, CommandArgInfo, CommandArgType,
5 ExecuteCommand,
6 },
7 CommandStatus, Repl,
8};
9use std::future::Future;
10use std::pin::Pin;
11
12struct DescribeCommandHandler {}
13impl DescribeCommandHandler {
14 pub fn new() -> Self {
15 Self {}
16 }
17 async fn handle_variant_1(&mut self) -> anyhow::Result<CommandStatus> {
18 println!("No arguments");
19 Ok(CommandStatus::Done)
20 }
21 async fn handle_variant_2(&mut self, a: i32, b: i32) -> anyhow::Result<CommandStatus> {
22 println!("Got two integers: {} {}", a, b);
23 Ok(CommandStatus::Done)
24 }
25 async fn handle_variant_3(&mut self, a: i32, b: String) -> anyhow::Result<CommandStatus> {
26 println!("An integer `{}` and a string `{}`", a, b);
27 Ok(CommandStatus::Done)
28 }
29}
30impl ExecuteCommand for DescribeCommandHandler {
31 fn execute(
32 &mut self,
33 args: Vec<String>,
34 args_info: Vec<CommandArgInfo>,
35 ) -> Pin<Box<dyn Future<Output = anyhow::Result<CommandStatus>> + '_>> {
36 let valid = validate(args.clone(), args_info.clone());
37 if let Err(e) = valid {
38 return Box::pin(lift_validation_err(Err(e)));
39 }
40
41 let variant_1 = validate(args.clone(), args_info);
46 if let Ok(()) = variant_1 {
47 return Box::pin(self.handle_variant_1());
48 }
49
50 let variant_2 = validate(
51 args.clone(),
52 vec![
53 CommandArgInfo::new_with_name(CommandArgType::I32, "a"),
54 CommandArgInfo::new_with_name(CommandArgType::I32, "b"),
55 ],
56 );
57 if let Ok(()) = variant_2 {
58 let a = args[0].parse::<i32>();
59 let b = args[1].parse::<i32>();
60
61 match (a, b) {
62 (Ok(a), Ok(b)) => {
63 return Box::pin(self.handle_variant_2(a, b));
64 }
65 _ => (),
66 }
67 }
68
69 let variant_3 = validate(
70 args.clone(),
71 vec![
72 CommandArgInfo::new_with_name(CommandArgType::I32, "a"),
73 CommandArgInfo::new_with_name(CommandArgType::String, "b"),
74 ],
75 );
76 if let Ok(()) = variant_3 {
77 let a = args[0].parse::<i32>();
78 let b = args[1].clone();
79
80 match a {
81 Ok(a) => {
82 return Box::pin(self.handle_variant_3(a, b));
83 }
84 _ => (),
85 }
86 }
87
88 Box::pin(lift_validation_err(Err(ArgsError::NoVariantFound)))
89 }
90}
91
92#[tokio::main]
93async fn main() -> anyhow::Result<()> {
94 #[rustfmt::skip]
95 let mut repl = Repl::builder()
96 .add("describe", Command::new(
97 "Variant 1",
98 vec![],
99 Box::new(DescribeCommandHandler::new()),
100 ))
101 .add("describe", Command::new(
102 "Variant 2",
103 vec![
104 CommandArgInfo::new_with_name(CommandArgType::I32, "a"),
105 CommandArgInfo::new_with_name(CommandArgType::I32, "b"),
106 ],
107 Box::new(DescribeCommandHandler::new()),
108 ))
109 .add("describe", Command::new(
110 "Variant 3",
111 vec![
112 CommandArgInfo::new_with_name(CommandArgType::I32, "a"),
113 CommandArgInfo::new_with_name(CommandArgType::String, "b"),
114 ],
115 Box::new(DescribeCommandHandler::new()),
116 ))
117 .build()
118 .context("Failed to create repl")?;
119
120 repl.run().await.context("Critical REPL error")?;
121
122 Ok(())
123}