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
use std::path::Path;
use credent_model::{Profile, Profiles};
use crate::{AppName, CredentialsFile, Error};
#[derive(Debug)]
pub struct CredentialsFileLoader;
impl CredentialsFileLoader {
pub async fn load(app_name: AppName<'_>) -> Result<Option<Profile>, Error> {
let credentials_path = CredentialsFile::path(app_name)?;
if credentials_path.exists() {
Self::load_profile(app_name, Profile::DEFAULT_NAME).await
} else {
Ok(None)
}
}
pub async fn load_profile(
app_name: AppName<'_>,
profile_name: &str,
) -> Result<Option<Profile>, Error> {
Self::load_all(app_name)
.await
.map(|profiles_result| {
profiles_result.map(|profiles| {
profiles
.0
.into_iter()
.find(|profile| profile.name == profile_name)
})
})
.map(Option::flatten)
}
pub async fn load_all(app_name: AppName<'_>) -> Result<Option<Profiles>, Error> {
let credentials_path = CredentialsFile::path(app_name)?;
if credentials_path.exists() {
Self::load_file(credentials_path.as_ref()).await.map(Some)
} else {
Ok(None)
}
}
pub async fn load_file(credentials_path: &Path) -> Result<Profiles, Error> {
if !credentials_path.exists() {
let credentials_path = credentials_path.to_owned();
Err(Error::CredentialsFileNonExistent { credentials_path })
} else if credentials_path.is_dir() {
let credentials_path = credentials_path.to_owned();
Err(Error::CredentialsFileIsDir { credentials_path })
} else {
let profiles_contents = Self::credentials_file_read(credentials_path).await?;
Self::credentials_deserialize(profiles_contents, credentials_path)
}
}
async fn credentials_file_read(credentials_path: &Path) -> Result<Vec<u8>, Error> {
async_fs::read(credentials_path).await.map_err(|io_error| {
let credentials_path = credentials_path.to_owned();
Error::CredentialsFileFailedToRead {
credentials_path,
io_error,
}
})
}
fn credentials_deserialize(
profiles_contents: Vec<u8>,
credentials_path: &Path,
) -> Result<Profiles, Error> {
toml::from_slice(&profiles_contents).map_err(|toml_de_error| {
let credentials_path = credentials_path.to_owned();
Error::CredentialsFileFailedToDeserialize {
credentials_path,
toml_de_error,
}
})
}
}