1use std::num::IntErrorKind;
2use teehistorian::chunks::ConsoleCommand;
3
4pub enum Command<'a> {
5 Team(i32),
6 ToggleLock,
7 SetLock(bool),
8 SaveEmpty,
9 Save(&'a [u8]),
10 Load(&'a [u8]),
11 Kill,
12 Team0Mode,
13 Pause,
14 Spec,
15}
16
17impl<'a> Command<'a> {
18 pub fn serialize(&self) -> String {
19 match self {
20 Command::Team(team) => format!("team {team}"),
21 Command::ToggleLock => "lock".to_string(),
22 Command::SetLock(lock) => format!("lock {}", *lock as u8),
23 Command::SaveEmpty => "save".to_string(),
24 Command::Save(s) => format!("save {}", std::str::from_utf8(s).unwrap()),
25 Command::Load(s) => format!("load {}", std::str::from_utf8(s).unwrap()),
26 Command::Kill => "kill".to_string(),
27 Command::Team0Mode => "team0mode".to_string(),
28 Command::Pause => "pause".to_string(),
29 Command::Spec => "spec".to_string(),
30 }
31 }
32
33 pub fn i32(param: &[u8]) -> i32 {
34 let _p: i64 = 0;
35 let param: &str = std::str::from_utf8(param).unwrap_or("0");
43 match param.parse::<i64>() {
44 Ok(i) => i as i32,
45 Err(err) => match err.kind() {
46 IntErrorKind::PosOverflow => i32::MAX,
47 IntErrorKind::NegOverflow => 0,
48 _ => 0,
49 },
50 }
51 }
52
53 pub fn from_teehistorian(cmd: &ConsoleCommand<'a>) -> Option<Self> {
54 match cmd.cmd {
55 b"team" => {
56 let arg = cmd.args.first()?;
57 let arg = std::str::from_utf8(arg).ok()?;
58 let team = arg.parse::<i32>().ok()?;
59 Some(Command::Team(team))
60 }
61 b"lock" => {
62 if let Some(arg) = cmd.args.first() {
63 let i = Command::i32(arg);
64 Some(Command::SetLock(i != 0))
65 } else {
66 Some(Command::ToggleLock)
67 }
68 }
69 b"unlock" => Some(Command::SetLock(false)),
70 b"load" => cmd.args.first().map(|arg| Command::Load(arg)),
71 b"save" => {
72 if let Some(arg) = cmd.args.first() {
73 Some(Command::Save(arg))
74 } else {
75 Some(Command::SaveEmpty)
76 }
77 }
78 b"kill" => Some(Command::Kill),
79 b"team0mode" => Some(Command::Team0Mode),
80 b"pause" => Some(Command::Pause),
81 b"spec" => Some(Command::Spec),
82 _ => None,
83 }
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::Command;
90
91 #[test]
92 fn serialize_commands() {
93 assert_eq!(Command::Team(1).serialize(), "team 1");
94 assert_eq!(Command::ToggleLock.serialize(), "lock");
95 assert_eq!(Command::SetLock(true).serialize(), "lock 1");
96 assert_eq!(Command::SetLock(false).serialize(), "lock 0");
97 assert_eq!(Command::Kill.serialize(), "kill");
98 assert_eq!(Command::Pause.serialize(), "pause");
99 assert_eq!(Command::Spec.serialize(), "spec");
100 assert_eq!(Command::SaveEmpty.serialize(), "save");
101 assert_eq!(Command::Save(b"abc").serialize(), "save abc");
102 assert_eq!(Command::Load(b"123").serialize(), "load 123");
103 assert_eq!(Command::Load(b"").serialize(), "load ");
104 assert_eq!(Command::Load(b"abc def").serialize(), "load abc def");
105 }
106}