persistent_keystore_rs/structs.rs
1use std::time::{SystemTime, Duration};
2use std::collections::HashMap;
3use std::hash::Hash;
4use serde_derive::{Serialize, Deserialize};
5use std::fmt;
6
7use crate::errors::*;
8
9#[derive(Hash, PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
10pub enum Field {
11 String(String),
12 I64(i64),
13 I32(i32),
14 U64(u64),
15 U32(u32),
16 Date(SystemTime),
17 Bool(bool),
18 NotImplemented,
19}
20
21impl Field {
22 pub fn get_type(&self) -> FieldType {
23 let t = match self {
24 Field::String(_) => FieldType::String,
25 Field::I32(_) => FieldType::I32,
26 Field::I64(_) => FieldType::I64,
27 Field::U64(_) => FieldType::U64,
28 Field::U32(_) => FieldType::U32,
29 Field::Date(_) => FieldType::Date,
30 Field::Bool(_) => FieldType::Bool,
31 Field::NotImplemented => FieldType::None,
32 };
33 t
34 }
35
36}
37
38impl fmt::Display for Field {
39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 let msg = match &self {
41 Field::String(v) => format!("{}", v),
42 Field::I32(v) => format!("{}", v),
43 Field::I64(v) => format!("{}", v),
44 Field::U64(v) => format!("{}", v),
45 Field::U32(v) => format!("{}", v),
46 Field::Date(v) => format!("{:?}", v),
47 Field::Bool(v) => format!("{}", v),
48 Field::NotImplemented => format!("NotImplemented"),
49 };
50 write!(f, "{}", msg)
51 }
52}
53
54#[derive(Hash, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
55pub enum FieldType {
56 String,
57 I64,
58 I32,
59 U64,
60 U32,
61 Date,
62 Bool,
63 None,
64}
65
66#[derive(Clone, Serialize, Deserialize)]
67pub enum FieldRequirement {
68 Required(FieldType),
69 Optional(FieldType)
70}
71
72impl FieldRequirement {
73 pub fn unwrap(&self) -> FieldType {
74 match self {
75 FieldRequirement::Required(f) => return f.clone(),
76 FieldRequirement::Optional(f) => return f.clone(),
77 }
78 }
79}
80
81/// Database; a collection of Tables
82#[derive(Serialize, Deserialize, Clone)]
83pub struct Database {
84 pub sync_interval: Option<Duration>,
85 tables: HashMap<String, Table>,
86}
87
88impl Default for Database {
89 fn default() -> Self {
90 Self{
91 sync_interval: None,
92 tables: HashMap::new(),
93 }
94 }
95}
96
97impl Database {
98 /// Sets the Sync Duration of the Database.
99 ///
100 /// Note this is currently only utilized by the Client
101 /// ```
102 /// use persistent_keystore_rs::Database;
103 /// use std::time::Duration;
104 ///
105 /// let mut database = Database::default();
106 /// database.set_sync_duration(Duration::from_secs(60));
107 /// ```
108 pub fn set_sync_duration(&mut self, duration: Duration) {
109 self.sync_interval = Some(duration)
110 }
111
112 /// Removes the Sync Duration of the Database.
113 ///
114 /// Note this is currently only utilized by the Client
115 /// ```
116 /// use persistent_keystore_rs::Database;
117 ///
118 /// let mut database = Database::default();
119 /// database.remove_sync_duration();
120 /// ```
121 pub fn remove_sync_duration(&mut self) {
122 self.sync_interval = None
123 }
124
125 /// Returns a mutable reference to a Table within the Database
126 /// ```
127 /// # use persistent_keystore_rs::{Table, FieldType};
128 /// use persistent_keystore_rs::Database;
129 /// # use std::time::Duration;
130 ///
131 /// # let table1 = Table::new()
132 /// # .name("MyTable".to_string())
133 /// # .primary_field(FieldType::String).unwrap()
134 /// # .add_field("Count".to_string(), FieldType::I64).unwrap()
135 /// # .add_optional_field("Notes".to_string(), FieldType::String).unwrap()
136 /// # .add_expiration(Duration::from_secs(60))
137 /// # .build().unwrap();
138 /// let mut database = Database::default();
139 /// # database.create_table(table1).unwrap();
140 /// let table = database.get_table(&"MyTable".to_string()).unwrap();
141 /// ```
142 pub fn get_table(&mut self, table: &String) -> Result<&mut Table, DatabaseError> {
143 match self.tables.get_mut(table) {
144 Some(t) => return Ok(t),
145 None => return Err(DatabaseError::TableDoesNotExist(table.clone()))
146 };
147 }
148
149 /// Creates a Table within the Database
150 /// ```
151 /// use persistent_keystore_rs::{Database, Table, FieldType};
152 /// use std::time::Duration;
153 ///
154 /// let table = Table::new()
155 /// .name("MyTable".to_string())
156 /// .primary_field(FieldType::String).unwrap()
157 /// .add_field("Count".to_string(), FieldType::I64).unwrap()
158 /// .add_optional_field("Notes".to_string(), FieldType::String).unwrap()
159 /// .add_expiration(Duration::from_secs(60))
160 /// .build().unwrap();
161 ///
162 /// let mut database = Database::default();
163 /// database.create_table(table).unwrap();
164 /// ```
165 pub fn create_table(&mut self, table: Table) -> Result<(), DatabaseError> {
166 self.tables.insert(table.name.clone(), table);
167 Ok(())
168 }
169
170 /// Deletes the specified Table within the Database
171 /// ```
172 /// # use persistent_keystore_rs::{Table, FieldType};
173 /// use persistent_keystore_rs::Database;
174 /// # use std::time::Duration;
175 ///
176 /// # let table1 = Table::new()
177 /// # .name("MyTable".to_string())
178 /// # .primary_field(FieldType::String).unwrap()
179 /// # .add_field("Count".to_string(), FieldType::I64).unwrap()
180 /// # .add_optional_field("Notes".to_string(), FieldType::String).unwrap()
181 /// # .add_expiration(Duration::from_secs(60))
182 /// # .build().unwrap();
183 /// let mut database = Database::default();
184 /// # database.create_table(table1).unwrap();
185 /// database.drop_table(&"MyTable".to_string()).unwrap();
186 /// ```
187 pub fn drop_table(&mut self, table: &String) -> Result<(), DatabaseError> {
188 match self.tables.remove(table) {
189 Some(_) => return Ok(()),
190 None => return Err(DatabaseError::TableDoesNotExist(table.clone())),
191 }
192 }
193
194 /// Returns a Vec of Table names that are stored within the Database
195 /// ```
196 /// # use persistent_keystore_rs::{Table, FieldType};
197 /// use persistent_keystore_rs::Database;
198 /// # use std::time::Duration;
199 ///
200 /// let mut database = Database::default();
201 /// # let table1 = Table::new()
202 /// # .name("MyTable".to_string())
203 /// # .primary_field(FieldType::String).unwrap()
204 /// # .add_field("Count".to_string(), FieldType::I64).unwrap()
205 /// # .add_optional_field("Notes".to_string(), FieldType::String).unwrap()
206 /// # .add_expiration(Duration::from_secs(60))
207 /// # .build().unwrap();
208 /// # database.create_table(table1).unwrap();
209 /// # let table2 = Table::new()
210 /// # .name("MySecondTable".to_string())
211 /// # .primary_field(FieldType::String).unwrap()
212 /// # .add_field("Count".to_string(), FieldType::I64).unwrap()
213 /// # .add_optional_field("Notes".to_string(), FieldType::String).unwrap()
214 /// # .add_expiration(Duration::from_secs(60))
215 /// # .build().unwrap();
216 /// # database.create_table(table2).unwrap();
217 /// let tables = database.list_tables();
218 /// # assert_eq!(tables.len(), 2);
219 /// # assert!(tables.contains(&"MyTable".to_string()));
220 /// # assert!(tables.contains(&"MySecondTable".to_string()));
221 /// ```
222 pub fn list_tables(&mut self) -> Vec<String> {
223 let mut results = Vec::new();
224 for k in self.tables.keys() {
225 results.push(k.clone());
226 };
227 results
228 }
229}
230
231/// Builder Pattern for creating a new Table
232pub struct TableBuilder {
233 table: Table,
234}
235
236impl TableBuilder {
237 /// Sets the Name of the Table
238 /// ```
239 /// use persistent_keystore_rs::Table;
240 /// let table = Table::new()
241 /// .name("MyTable".to_string());
242 /// ```
243 pub fn name(mut self, name: String) -> Self {
244 self.table.name = name;
245 self
246 }
247
248 /// Sets the FieldType of the primary_field
249 /// ```
250 /// use persistent_keystore_rs::{Table, FieldType};
251 /// let table = Table::new()
252 /// # .name("MyTable".to_string())
253 /// .primary_field(FieldType::String).unwrap();
254 /// ```
255 pub fn primary_field(mut self, priary_key: FieldType) -> Result<Self, DatabaseError> {
256 if let FieldType::None = priary_key {
257 return Err(DatabaseError::UnsupportedFieldType)
258 };
259 self.table.primary_field = priary_key;
260 Ok(self)
261 }
262
263 /// Add a required field of FieldType and name to the Table
264 /// ```
265 /// use persistent_keystore_rs::{Table, FieldType};
266 /// let table = Table::new()
267 /// # .name("MyTable".to_string())
268 /// # .primary_field(FieldType::String).unwrap()
269 /// .add_field("Count".to_string(), FieldType::I64).unwrap();
270 /// ```
271 pub fn add_field(mut self, key: String, field_type: FieldType) -> Result<Self, DatabaseError> {
272 if let FieldType::None = field_type {
273 return Err(DatabaseError::UnsupportedFieldType)
274 };
275
276 self.table.fields.insert(key, FieldRequirement::Required(field_type));
277 Ok(self)
278 }
279
280 /// Add an optional field of FieldType and name to the Table
281 /// ```
282 /// use persistent_keystore_rs::{Table, FieldType};
283 /// let table = Table::new()
284 /// # .name("MyTable".to_string())
285 /// # .primary_field(FieldType::String).unwrap()
286 /// # .add_field("Count".to_string(), FieldType::I64).unwrap()
287 /// .add_optional_field("Notes".to_string(), FieldType::String).unwrap();
288 /// ```
289 pub fn add_optional_field(mut self, key: String, field_type: FieldType) -> Result<Self, DatabaseError> {
290 if let FieldType::None = field_type {
291 return Err(DatabaseError::UnsupportedFieldType)
292 };
293
294 self.table.fields.insert(key, FieldRequirement::Optional(field_type));
295 Ok(self)
296 }
297
298 /// Add an expiration Duration to the Table. The timer for the expiration
299 /// is set to the last time an Entry was updated.
300 ///
301 /// Note that this does not happen automatically within this struct; but is utilized
302 /// within Client
303 /// ```
304 /// use persistent_keystore_rs::{Table, FieldType};
305 /// use std::time::Duration;
306 ///
307 /// let table = Table::new()
308 /// # .name("MyTable".to_string())
309 /// # .primary_field(FieldType::String).unwrap()
310 /// # .add_field("Count".to_string(), FieldType::I64).unwrap()
311 /// # .add_optional_field("Notes".to_string(), FieldType::String).unwrap()
312 /// .add_expiration(Duration::from_secs(60));
313 /// ```
314 pub fn add_expiration(mut self, expire_after: Duration) -> Self {
315 self.table.expire_after = Some(expire_after);
316 self
317 }
318
319 /// Validates the Table is properly configured and returns the Table object.
320 /// ```
321 /// use persistent_keystore_rs::{Table, FieldType};
322 /// use std::time::Duration;
323 ///
324 /// let table = Table::new()
325 /// .name("MyTable".to_string())
326 /// .primary_field(FieldType::String).unwrap()
327 /// .add_field("Count".to_string(), FieldType::I64).unwrap()
328 /// .add_optional_field("Notes".to_string(), FieldType::String).unwrap()
329 /// .add_expiration(Duration::from_secs(60))
330 /// .build();
331 /// ```
332 pub fn build(self) -> Result<Table, DatabaseError> {
333 if let FieldType::None = self.table.primary_field {
334 return Err(DatabaseError::TableMissingPrimaryKey)
335
336 } else if self.table.name.len() == 0 {
337 return Err(DatabaseError::TableNameNotSet)
338
339 } else if self.table.fields.len() == 0 {
340 return Err(DatabaseError::TableMustContainFields)
341 };
342
343 Ok(self.table)
344 }
345}
346
347/// Table is a collection of Entry objects that meet a specified format criteria
348#[derive(Serialize, Deserialize, Clone)]
349pub struct Table {
350 pub name: String,
351 pub primary_field: FieldType,
352 pub fields: HashMap<String, FieldRequirement>,
353 entries: HashMap<Field, Entry>,
354 pub expire_after: Option<Duration>,
355}
356
357impl Table {
358 /// Returns a TableBuilder Instance that will be used to create a new table
359 /// ```
360 /// use persistent_keystore_rs::Table;
361 /// let table = Table::new();
362 /// ```
363 pub fn new() -> TableBuilder {
364 TableBuilder{
365 table: Table{
366 name: String::new(),
367 primary_field: FieldType::None,
368 fields: HashMap::new(),
369 entries: HashMap::new(),
370 expire_after: None,
371 }
372 }
373 }
374
375 /// Returns a reference to an Entry within the Table matching the primary Field
376 /// If the primary Field does not exist, DatabaseError::EntryDoesNotExists is returned.
377 /// ```
378 /// # use persistent_keystore_rs::{Table, Entry, FieldType};
379 /// use persistent_keystore_rs::Field;
380 /// # use std::time::{Duration, SystemTime};
381 /// # let mut table = Table::new()
382 /// # .name(String::from("MyTable"))
383 /// # .primary_field(FieldType::String).unwrap()
384 /// # .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
385 /// # .add_expiration(Duration::from_secs(2592000))
386 /// # .build().unwrap();
387 /// # let entry = Entry::new()
388 /// # .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
389 /// # .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
390 /// # .build().unwrap();
391 /// # table.insert(entry).unwrap();
392 /// let result = table.get(&Field::String("MyFirstEntry".to_string())).unwrap();
393 /// ```
394 pub fn get(&self, key: &Field) -> Result<&Entry, DatabaseError> {
395 match self.entries.get_key_value(key) {
396 Some((_, v)) => return Ok(v),
397 None => return Err(DatabaseError::EntryDoesNotExists),
398 }
399 }
400
401 /// Inserts the provided entry into the Table
402 /// If the primary Field exists, DatabaseError::EntryExists is returned.
403 /// ```
404 /// # use persistent_keystore_rs::{Table, FieldType};
405 /// use persistent_keystore_rs::{Entry, Field};
406 /// # use std::time::{Duration, SystemTime};
407 /// # let mut table = Table::new()
408 /// # .name(String::from("MyTable"))
409 /// # .primary_field(FieldType::String).unwrap()
410 /// # .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
411 /// # .add_expiration(Duration::from_secs(2592000))
412 /// # .build().unwrap();
413 /// let entry = Entry::new()
414 /// .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
415 /// .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
416 /// .build().unwrap();
417 /// table.insert(entry).unwrap();
418 /// ```
419 pub fn insert(&mut self, mut entry: Entry) -> Result<(), DatabaseError> {
420 self.validate_field_types(&entry)?;
421 self.validate_required_fields(&entry)?;
422 entry.last_timestamp = Some(SystemTime::now());
423
424 match self.get(&entry.primary_field) {
425 Ok(_) => return Err(DatabaseError::EntryExists),
426 Err(_) => {
427
428 match self.entries.insert(entry.primary_field.clone(), entry) {
429 Some(_) => {},
430 None => {}
431 }
432 }
433 }
434 Ok(())
435 }
436
437 /// Inserts the provided entry if it doesn't exist, or updates if it does
438 /// ```
439 /// # use persistent_keystore_rs::{Table, FieldType};
440 /// use persistent_keystore_rs::{Entry, Field};
441 /// # use std::time::{Duration, SystemTime};
442 /// # let mut table = Table::new()
443 /// # .name(String::from("MyTable"))
444 /// # .primary_field(FieldType::String).unwrap()
445 /// # .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
446 /// # .add_expiration(Duration::from_secs(2592000))
447 /// # .build().unwrap();
448 /// let entry = Entry::new()
449 /// .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
450 /// .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
451 /// .build().unwrap();
452 ///
453 /// table.insert_or_update(entry).unwrap();
454 ///
455 /// let entry2 = Entry::new()
456 /// .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
457 /// .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
458 /// .build().unwrap();
459 ///
460 /// table.insert_or_update(entry2).unwrap();
461 /// ```
462 pub fn insert_or_update(&mut self, entry: Entry) -> Result<(), DatabaseError> {
463 return self.update(entry)
464 }
465
466 /// Updates the provided entry within the Table.
467 /// If the Entry does not exist, DatabaseError:EntryDoesNotExists is returned
468 /// ```
469 /// # use persistent_keystore_rs::{Table, FieldType};
470 /// use persistent_keystore_rs::{Entry, Field};
471 /// # use std::time::{Duration, SystemTime};
472 /// # let mut table = Table::new()
473 /// # .name(String::from("MyTable"))
474 /// # .primary_field(FieldType::String).unwrap()
475 /// # .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
476 /// # .add_expiration(Duration::from_secs(2592000))
477 /// # .build().unwrap();
478 /// # let entry2 = Entry::new()
479 /// # .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
480 /// # .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
481 /// # .build().unwrap();
482 /// # table.insert_or_update(entry2).unwrap();
483 ///
484 /// let entry = Entry::new()
485 /// .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
486 /// .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
487 /// .build().unwrap();
488 ///
489 /// table.update(entry).unwrap();
490 /// ```
491 pub fn update(&mut self, mut entry: Entry) -> Result<(), DatabaseError> {
492 self.validate_field_types(&entry)?;
493 self.validate_required_fields(&entry)?;
494 entry.last_timestamp = Some(SystemTime::now());
495
496 match self.entries.insert(entry.primary_field.clone(), entry) {
497 Some(_) => {},
498 None => {}
499 }
500 Ok(())
501 }
502
503 /// Validates that all required fields are provided and that no fields are provided
504 /// that are not configured in the table.
505 fn validate_required_fields(&self, entry: &Entry) -> Result<(), DatabaseError> {
506 let mut fields: Vec<&String> = Vec::new();
507 for k in self.fields.keys() {
508 fields.push(k);
509 };
510
511 for (k, _) in &entry.fields {
512 if self.fields.contains_key(k) {
513 match fields.iter().position(|r| r == &k) {
514 Some(index) => {
515 fields.remove(index);
516 },
517 None => return Err(DatabaseError::UnsupportedField(k.clone())),
518 }
519 } else {
520 return Err(DatabaseError::UnsupportedField(k.clone()))
521 }
522 }
523
524 for f in fields {
525 match self.fields.get_key_value(f) {
526 Some((_, requirement)) => {
527 match requirement {
528 FieldRequirement::Required(_) => return Err(DatabaseError::MissingRequiredField(f.clone())),
529 FieldRequirement::Optional(_) => {},
530 }
531 },
532 None => {}
533 }
534 };
535
536 Ok(())
537 }
538
539 /// Validates that the fields provided within the entry, matches the field types
540 /// of the Entry with the field types specified in the table.
541 fn validate_field_types(&self, entry: &Entry) -> Result<(), DatabaseError> {
542 if self.primary_field != entry.primary_field.get_type() {
543 return Err(DatabaseError::MismatchedFieldType)
544 };
545
546 for (k, v) in &entry.fields {
547 match self.fields.get_key_value(k) {
548 Some((_, value)) => {
549 if value.clone().unwrap() != v.get_type() {
550 return Err(DatabaseError::MismatchedFieldType)
551 }
552 },
553 None => {},
554 }
555 }
556 Ok(())
557 }
558
559 /// Deletes the entry with the associated primary_field from the Table.
560 /// If the Entry does not exist, DatabaseError:EntryDoesNotExists is returned
561 /// ```
562 /// # use persistent_keystore_rs::{Table, Entry, FieldType};
563 /// use persistent_keystore_rs::Field;
564 /// # use std::time::{Duration, SystemTime};
565 /// # let mut table = Table::new()
566 /// # .name(String::from("MyTable"))
567 /// # .primary_field(FieldType::String).unwrap()
568 /// # .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
569 /// # .add_expiration(Duration::from_secs(2592000))
570 /// # .build().unwrap();
571 /// # let entry = Entry::new()
572 /// # .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
573 /// # .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
574 /// # .build().unwrap();
575 /// # table.insert_or_update(entry).unwrap();
576 /// table.delete(Field::String("MyFirstEntry".to_string())).unwrap();
577 /// ```
578 pub fn delete(&mut self, primary_field: Field) -> Result<(), DatabaseError> {
579 match self.entries.remove_entry(&primary_field) {
580 Some(_) => return Ok(()),
581 None => return Err(DatabaseError::EntryDoesNotExists),
582 }
583 }
584
585 /// Returns all Entries from the Table
586 /// ```
587 /// # use persistent_keystore_rs::{Table, Entry, Field, FieldType};
588 /// # use std::time::{Duration, SystemTime};
589 /// # let mut table = Table::new()
590 /// # .name(String::from("MyTable"))
591 /// # .primary_field(FieldType::String).unwrap()
592 /// # .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
593 /// # .add_expiration(Duration::from_secs(2592000))
594 /// # .build().unwrap();
595 /// # let entry = Entry::new()
596 /// # .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
597 /// # .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
598 /// # .build().unwrap();
599 /// # table.insert(entry).unwrap();
600 /// # let entry2 = Entry::new()
601 /// # .set_primary_field(Field::String("MySecondEntry".to_string())).unwrap()
602 /// # .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
603 /// # .build().unwrap();
604 /// # table.insert(entry2).unwrap();
605 /// # let entry3 = Entry::new()
606 /// # .set_primary_field(Field::String("MyThirdEntry".to_string())).unwrap()
607 /// # .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
608 /// # .build().unwrap();
609 /// # table.insert(entry3).unwrap();
610 /// let results = table.scan().unwrap();
611 /// # assert_eq!(results.len(), 3);
612 /// ```
613 pub fn scan(&self) -> Result<Vec<Entry>, DatabaseError> {
614 let mut results = Vec::new();
615 for (_, v) in &self.entries {
616 results.push(v.clone())
617 };
618 Ok(results)
619 }
620}
621
622/// Entry represents all items that are contained within a Table
623#[derive(Clone, Serialize, Debug, Deserialize, PartialEq, Eq)]
624pub struct Entry {
625 pub primary_field: Field,
626 pub fields: HashMap<String, Field>,
627 pub last_timestamp: Option<SystemTime>,
628}
629
630impl Entry {
631 /// Returns an EntryBuilder Instance that will be used to create a new entry
632 /// ```
633 /// use persistent_keystore_rs::Entry;
634 /// let entry = Entry::new();
635 /// ```
636 pub fn new() -> EntryBuilder {
637 EntryBuilder{
638 entry: Entry{
639 primary_field: Field::NotImplemented,
640 fields: HashMap::new(),
641 last_timestamp: None,
642 }
643 }
644 }
645
646 /// Returns an Optional Field value for a given Entry
647 /// ```
648 /// use persistent_keystore_rs::{Entry, Field};
649 /// use std::time::SystemTime;
650 /// let entry = Entry::new()
651 /// .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
652 /// .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
653 /// .build().unwrap();
654 ///
655 /// let exists = &entry.get_field("TimeStamp".to_string());
656 /// # if let None = exists {
657 /// # panic!("Field should exist");
658 /// # };
659 ///
660 /// # if let Some(_) = &entry.get_field("DoesNotExist".to_string()) {
661 /// # panic!("Field should not exist");
662 /// # }
663 /// ```
664 ///
665 pub fn get_field(&self, key: String) -> Option<Field> {
666 if let Some((_, v)) = self.fields.get_key_value(&key) {
667 return Some(v.clone());
668 };
669 None
670 }
671}
672
673impl fmt::Display for Entry {
674 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
675 let msg = match &self.primary_field {
676 Field::String(v) => format!("{}", v),
677 Field::I32(v) => format!("{}", v),
678 Field::I64(v) => format!("{}", v),
679 Field::U64(v) => format!("{}", v),
680 Field::U32(v) => format!("{}", v),
681 Field::Date(v) => format!("{:?}", v),
682 Field::Bool(v) => format!("{}", v),
683 Field::NotImplemented => format!("NotImplemented"),
684 };
685 write!(f, "{}", msg)
686 }
687}
688
689/// Builder Pattern for creating new Entry items to be inserted into a Table
690pub struct EntryBuilder {
691 entry: Entry,
692}
693
694impl EntryBuilder {
695 /// Sets the primary_field of the Entry
696 /// ```
697 /// use persistent_keystore_rs::{Entry, Field};
698 /// let mut entry_builder = Entry::new()
699 /// .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap();
700 /// ```
701 pub fn set_primary_field(mut self, field: Field) -> Result<Self, DatabaseError> {
702 if let FieldType::None = field.get_type() {
703 return Err(DatabaseError::InvalidPrimaryKey)
704 };
705 self.entry.primary_field = field;
706 Ok(self)
707 }
708
709 /// Add a field to the Entry. This can include both required and optional fields.
710 /// ```
711 /// use persistent_keystore_rs::{Entry, Field};
712 /// let mut entry_builder = Entry::new()
713 /// .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
714 /// .add_field("Count".to_string(), Field::I32(0)).unwrap();
715 /// ```
716 pub fn add_field(mut self, key: String, field: Field) -> Result<Self, DatabaseError> {
717 if let FieldType::None = field.get_type() {
718 return Err(DatabaseError::UnsupportedFieldType)
719 };
720
721 if key.len() == 0 {
722 return Err(DatabaseError::InvalidPrimaryKey)
723 }
724
725 self.entry.fields.insert(key, field);
726 Ok(self)
727 }
728
729 /// Validates the Entry is properly formatted with a primary field and contains at least one
730 /// value field.
731 /// ```
732 /// use persistent_keystore_rs::{Entry, Field};
733 /// let entry = Entry::new()
734 /// .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
735 /// .add_field("Count".to_string(), Field::I32(3)).unwrap()
736 /// .build().unwrap();
737 /// ```
738 pub fn build(self) -> Result<Entry, DatabaseError> {
739 if let FieldType::None = self.entry.primary_field.get_type() {
740 return Err(DatabaseError::InvalidPrimaryKey)
741 };
742
743 if self.entry.fields.len() == 0 {
744 return Err(DatabaseError::EntryMustContainFields)
745 }
746
747 Ok(self.entry)
748 }
749}
750
751#[cfg(test)]
752mod tests {
753 use super::*;
754
755 #[test]
756 fn entry_field_some() {
757 let entry = Entry::new()
758 .set_primary_field(Field::String("This should Succeed too".to_string())).unwrap()
759 .add_field("FirstKey".to_string(), Field::I64(12312312)).unwrap()
760 .add_field("OptionalKey".to_string(), Field::String("My second entry".to_string())).unwrap()
761 .build().unwrap();
762
763 if let None = entry.get_field("FirstKey".to_string()) {
764 panic!("Expected value, received none")
765 }
766 }
767
768 #[test]
769 fn entry_field_none() {
770 let entry = Entry::new()
771 .set_primary_field(Field::String("This should Succeed too".to_string())).unwrap()
772 .add_field("FirstKey".to_string(), Field::I64(12312312)).unwrap()
773 .add_field("OptionalKey".to_string(), Field::String("My second entry".to_string())).unwrap()
774 .build().unwrap();
775
776 if let Some(s) = entry.get_field("MissingKey".to_string()) {
777 panic!("Expected None, received {}", s)
778 }
779 }
780}