1use core::str;
2use std::collections::HashMap;
3
4use serde::{Deserialize, Serialize};
5
6use crate::reads::Reads;
7use crate::schema::Schema;
8use crate::store::Store;
9use crate::{
10 action::{Action, Record},
11 command::Commands,
12 operation::{Operation, Operations},
13};
14
15#[derive(Debug, Serialize, Deserialize)]
16pub struct Vault {
17 data: HashMap<String, Store>,
18}
19
20impl Default for Vault {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26impl Vault {
27 pub fn new() -> Vault {
28 Self {
29 data: HashMap::new(),
30 }
31 }
32
33 fn step(&self, reads: &mut Reads<Store>, operation: Operation) -> Action {
34 match operation {
35 Operation::Get { key } => {
36 if let Some(value) = self.data.get(&key) {
37 reads.insert(key, value.clone());
38 }
39 Action::Noop
40 }
41 Operation::Set { key, value } => {
42 let previous = match value {
43 None => reads.remove(&key),
44 Some(ref v) => reads.insert(key.clone(), v.clone()),
45 };
46 Action::Replace {
47 key,
48 start: previous,
49 end: value,
50 }
51 }
52 }
53 }
54
55 fn operate(&mut self, operations: Operations) -> (Reads<Store>, Record) {
56 let mut record = Record::new();
57 let mut reads = Reads::new();
58 for operation in operations {
59 let action = self.step(&mut reads, operation);
60 record.push(action);
61 }
62
63 (reads, record)
64 }
65
66 pub fn transaction(&mut self, commands: Commands) -> (Reads<Store>, Record) {
67 self.operate(commands.into())
68 }
69
70 fn apply_action(&mut self, action: Action) {
71 if let Action::Replace { key, start: _, end } = action {
72 match end {
73 Some(value) => {
74 self.data.insert(key, value);
75 }
76 None => {
77 self.data.remove(&key);
78 }
79 }
80 }
81 }
82
83 pub fn apply_record(&mut self, record: Record) {
84 for action in record {
85 self.apply_action(action)
86 }
87 }
88
89 pub fn keys(self) -> Vec<String> {
90 self.data.into_keys().collect()
91 }
92
93 pub fn schema(self) -> Schema {
94 self.data
95 .into_iter()
96 .map(|(key, value)| (key, value.repr()))
97 .collect::<HashMap<String, String>>()
98 .into()
99 }
100}