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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright (c) 2023 Nick Piaddo
// SPDX-License-Identifier: Apache-2.0 OR MIT
// From dependency library
use typed_builder::TypedBuilder;
// From standard library
use std::path::PathBuf;
// From this library
use crate::cache::{Cache, CacheBuilderError};
#[derive(Debug, TypedBuilder)]
#[builder(builder_type(name = CacheBuilder, vis = "pub", doc ="Configure and instantiate a [`Cache`].\n\nFor usage, see [`CacheBuilder::build`]."),
build_method(vis = "", name = __build))]
pub(crate) struct Builder {
#[builder(setter(
strip_bool,
doc = r"Discards changes when a [`Cache`] instance goes out of scope.
- **Note:** `discard_changes_on_drop` and `auto_save_changes_to` are **mutually exclusive**."
))]
discard_changes_on_drop: bool,
#[builder(
default,
setter(
into,
strip_option,
doc = r"Saves changes to disk, automatically, when [`Cache`] goes out of scope.
# Argument
`destination` -- name of the file to save the cache's content into.
- **Note:** `discard_changes_on_drop` and `auto_save_changes_to` are **mutually exclusive**.
"
)
)]
// FIXME find a way to have a custom setter name different from the field name
// i.e. how to have
//
// pub fn auto_save_changes_to( self, dest_file: P)
//
// instead of the current default
//
// pub fn auto_save_changes_to( self, auto_save_changes_to: P)
//
// Ask question with example
//
// struct Fraction {
// n: i64,
// d: i64,
// }
//
// Can we have FractionBuilder with setters with custom names?:
//
// numerator(n: i64)
// denominator(d: i64(
auto_save_changes_to: Option<PathBuf>,
}
#[allow(non_camel_case_types)]
impl<
__discard_changes_on_drop: ::typed_builder::Optional<bool>,
__auto_save_changes_to: ::typed_builder::Optional<Option<PathBuf>>,
> CacheBuilder<(__discard_changes_on_drop, __auto_save_changes_to)>
{
/// Builds a new [`Cache`] instance.
///
/// # Examples
/// ----
///
/// ```
/// use rsblkid::cache::Cache;
/// use std::error::Error;
/// use std::path::Path;
/// use tempfile::NamedTempFile;
///
/// fn main() -> Result<(), Box<dyn Error>> {
///
/// // Create a cache that automatically saves changes to the default cache file
/// // (`blkid.tab`) when dropped.
/// let result = Cache::builder().build();
///
/// assert!(result.is_ok());
///
/// // Create a cache that automatically saves changes to a custom cache file when dropped.
/// let temp_file = NamedTempFile::new()?; // Create a temporary destination file in `/tmp`.
/// let result = Cache::builder()
/// .auto_save_changes_to(temp_file.path())
/// .build();
///
/// assert!(result.is_ok());
///
/// // Create a cache that automatically discards changes when dropped.
/// let result = Cache::builder().discard_changes_on_drop().build();
///
/// assert!(result.is_ok());
///
/// Ok(())
/// }
/// ```
///
pub fn build(self) -> Result<Cache, CacheBuilderError> {
log::debug!("CacheBuilder::build configuring new `Cache` instance");
let builder = self.__build();
let discard_file = "/dev/null";
match (
builder.discard_changes_on_drop,
builder.auto_save_changes_to,
) {
// Default (i.e. save changes to `blkid.tab`.
(false, None) => {
log::debug!("CacheBuilder::build new default cache");
Cache::new_default().map_err(CacheBuilderError::Cache)
}
// Can not save to empty path, defaults to `blkid.tab`.
(false, Some(path)) if path.as_os_str().is_empty() => {
log::debug!("CacheBuilder::build new default cache (given empty destination)");
Cache::new_default().map_err(CacheBuilderError::Cache)
}
// Save cache to...
(false, Some(path)) => {
log::debug!(
"CacheBuilder::build new cache, saving data on drop to {}",
path.display()
);
Cache::new_auto_save_changes_to(path).map_err(CacheBuilderError::Cache)
}
// Discard changes.
(true, None) => {
log::debug!("CacheBuilder::build new cache, discarding data on drop");
Cache::new_auto_save_changes_to(discard_file).map_err(CacheBuilderError::Cache)
}
// Can not both Discard AND Save.
(true, Some(_)) => {
let discard = "discard_changes_on_drop";
let auto_save = "auto_save_changes_to";
log::debug!(
"CacheBuilder::build called two mutually exclusive setters: `{}` and `{}`",
discard,
auto_save
);
let err_msg = format!(
"can not set `{}` and `{}` simultaneously",
discard, auto_save
);
Err(CacheBuilderError::MutuallyExclusive(err_msg))
}
}
}
}