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}