pants_store/
command.rs

1use std::error::Error;
2
3use crate::{
4    cli::{CLICommands, EntryStyle},
5    errors::ConversionError,
6    schema::Schema,
7    store::Store,
8};
9
10#[derive(Debug, Clone)]
11pub enum Instructions {
12    Interaction(Interaction),
13    Commands(Commands),
14}
15
16#[derive(Debug, Clone)]
17pub enum Command {
18    Read { key: String },
19    Update { key: String, value: Store },
20    Delete { key: String },
21}
22
23#[derive(Debug, Clone)]
24pub enum Interaction {
25    List,
26    Backup,
27    Rotate,
28}
29
30#[derive(Debug, Clone)]
31pub struct Commands {
32    pub commands: Vec<Command>,
33}
34
35impl IntoIterator for Commands {
36    type Item = Command;
37    type IntoIter = std::vec::IntoIter<Self::Item>;
38
39    fn into_iter(self) -> Self::IntoIter {
40        self.commands.into_iter()
41    }
42}
43
44impl Default for Commands {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50impl Commands {
51    pub fn new() -> Self {
52        Self { commands: vec![] }
53    }
54
55    pub fn push(&mut self, command: Command) {
56        self.commands.push(command);
57    }
58
59    // pub fn add(mut self, command: Command) -> Self {
60    //     self.commands.push(command);
61    //     self
62    // }
63}
64
65impl Instructions {
66    fn handle_new(name: String, schema: Schema, style: &str) -> Result<Self, Box<dyn Error>> {
67        match schema.get(&name) {
68            Some(_) => Err(Box::new(ConversionError::Exists)),
69            None => {
70                let value = Store::prompt(style)?;
71                let commands: Commands = vec![Command::Update { key: name, value }].into();
72                Ok(commands.into())
73            }
74        }
75    }
76    pub fn from_commands(commands: CLICommands, schema: Schema) -> Result<Self, Box<dyn Error>> {
77        match commands {
78            CLICommands::New { style } => match style {
79                EntryStyle::Password { name } => Self::handle_new(name, schema, "password"),
80                EntryStyle::UsernamePassword { name } => {
81                    Self::handle_new(name, schema, "username-password")
82                }
83            },
84            CLICommands::Get { key } => {
85                let commands: Commands = vec![Command::Read { key }].into();
86                Ok(commands.into())
87            }
88            CLICommands::Update { key } => match schema.get(&key) {
89                None => Err(Box::new(ConversionError::NoEntry)),
90                Some(value) => {
91                    let value = Store::prompt(value)?;
92                    let commands: Commands = vec![Command::Update { key, value }].into();
93                    Ok(commands.into())
94                }
95            },
96            CLICommands::Delete { key } => {
97                let commands: Commands = vec![Command::Delete { key }].into();
98                Ok(commands.into())
99            }
100            CLICommands::List => Ok(Interaction::List.into()),
101            CLICommands::Backup => Ok(Interaction::Backup.into()),
102            CLICommands::Rotate => Ok(Interaction::Rotate.into()),
103            _ => todo!(),
104        }
105    }
106}
107
108impl From<Vec<Command>> for Commands {
109    fn from(value: Vec<Command>) -> Self {
110        Self { commands: value }
111    }
112}
113
114impl From<Commands> for Instructions {
115    fn from(value: Commands) -> Self {
116        Instructions::Commands(value)
117    }
118}
119
120impl From<Interaction> for Instructions {
121    fn from(value: Interaction) -> Self {
122        Instructions::Interaction(value)
123    }
124}