storage/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Re-export modules
mod error;
mod file_store;
pub mod store;
pub mod validation;

// Re-export traits and structs
pub use error::Error;
pub use file_store::{FileStore, FileStoreConfig};
pub use store::MazeItem;
pub use store::MazeStore;
pub use store::Store;
pub use store::SharedStore;
pub use store::UserStore;

/// Represents the supported store configurations
pub enum StoreConfig {
    File(FileStoreConfig),
}

/// Creates and returns a store of the given type
///
/// # Returns
///
/// A new store instance if successful
///
/// # Examples
///
/// Try to create and then reload a maze from within a file store and, if successful, print it
///
/// ```
/// # // Make sure the store is in a suitable state prior to running the doc test
/// # use storage::test_setup::setup;
/// # setup();
///
/// use data_model::{Maze, User};
/// use maze::{MazePath, MazePrinter};
/// use storage::{FileStoreConfig, get_store, Store,  StoreConfig, Error};
/// use utils::StdoutLinePrinter;
///
/// let grid: Vec<Vec<char>> = vec![
///    vec!['S', ' ', 'W'],
///    vec![' ', 'F', 'W']
/// ];
/// let mut maze_to_create = Maze::from_vec(grid);
/// maze_to_create.name = "maze_1".to_string();
///
/// // Access the file store
/// let file_config = FileStoreConfig::default();
/// match get_store(StoreConfig::File(file_config)) {
///     Ok(mut store) => {
///         // Locate the owner by username
///         let find_user_result: Result<User, Error> = store.find_user_by_name("a_username");
///         let owner = match find_user_result {
///             Ok(user) => user,
///             Err(error) => {
///                 println!("Error fetching user: {:?}", error);
///                 return ;
///             }
///         };
///
///         // Create the maze within the store
///         if let Err(error) = store.create_maze(&owner, &mut maze_to_create) {
///             panic!(
///                 "failed to create maze => {}",
///                 error
///             );
///         }
///         // Now reload the maze from the store
///         match store.get_maze(&owner, &maze_to_create.id) {
///             Ok(loaded_maze) => {
///                 println!("Successfully loaded maze:");
///                 let mut print_target = StdoutLinePrinter::new();
///                 let empty_path = MazePath { points: vec![] };
///                 loaded_maze.print(&mut print_target, empty_path);
///             }
///             Err(error) => {
///                 panic!(
///                     "failed to load maze with id '{}' => {}",
///                     maze_to_create.id,
///                     error
///                 );
///             }
///         }
///     }
///     Err(error) => {
///         panic!(
///             "failed to access file store => {}",
///             error
///         );
///     }
/// }
/// ```
pub fn get_store(config: StoreConfig) -> Result<Box<dyn Store>, Error> {
    let store = match config
    {
        StoreConfig::File(file_config) => file_store::FileStore::new(&file_config),
    };

    Ok(Box::new(store))
}

/// Hidden module that provides setup functionality for doc tests.
#[doc(hidden)]
pub mod test_setup {
    use crate::{FileStore, FileStoreConfig, store::Manage};
    /// This function runs before every documentation test
    pub fn setup() {
        // Make sure any existing files and directories are cleared out
        let mut store = FileStore::new(&FileStoreConfig::default());
        if let Err(error) = store.empty() {
            panic!("setup() failed to empty store: {}", error);
        }
    }
}