1use std::{fmt, path::PathBuf};
2
3use redis::RedisError;
4#[cfg(feature = "serde")]
5use serde_1::{Deserialize, Serialize};
6
7use crate::{CreatePoolError, Pool, PoolBuilder, PoolConfig, RedisResult, Runtime};
8
9#[derive(Clone, Debug)]
45#[cfg_attr(feature = "serde", derive(serde_1::Deserialize, serde_1::Serialize))]
46#[cfg_attr(feature = "serde", serde(crate = "serde_1"))]
47pub struct Config {
48 pub urls: Option<Vec<String>>,
52
53 pub connections: Option<Vec<ConnectionInfo>>,
55
56 pub pool: Option<PoolConfig>,
58}
59
60impl Config {
61 pub fn create_pool(&self, runtime: Option<Runtime>) -> Result<Pool, CreatePoolError> {
67 let mut builder = self.builder().map_err(CreatePoolError::Config)?;
68 if let Some(runtime) = runtime {
69 builder = builder.runtime(runtime);
70 }
71 builder.build().map_err(CreatePoolError::Build)
72 }
73
74 pub fn builder(&self) -> Result<PoolBuilder, ConfigError> {
80 let manager = match (&self.urls, &self.connections) {
81 (Some(urls), None) => {
82 crate::Manager::new(urls.iter().map(|url| url.as_str()).collect())?
83 }
84 (None, Some(connections)) => crate::Manager::new(connections.clone())?,
85 (None, None) => crate::Manager::new(vec![ConnectionInfo::default()])?,
86 (Some(_), Some(_)) => return Err(ConfigError::UrlAndConnectionSpecified),
87 };
88 let pool_config = self.get_pool_config();
89 Ok(Pool::builder(manager).config(pool_config))
90 }
91
92 #[must_use]
95 pub fn get_pool_config(&self) -> PoolConfig {
96 self.pool.unwrap_or_default()
97 }
98
99 #[must_use]
102 pub fn from_urls<T: Into<Vec<String>>>(urls: T) -> Config {
103 Config {
104 urls: Some(urls.into()),
105 connections: None,
106 pool: None,
107 }
108 }
109}
110
111impl Default for Config {
112 fn default() -> Self {
113 Self {
114 urls: None,
115 connections: Some(vec![ConnectionInfo::default()]),
116 pool: None,
117 }
118 }
119}
120
121#[derive(Clone, Debug)]
125#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
126#[cfg_attr(feature = "serde", serde(crate = "serde_1"))]
127pub enum ConnectionAddr {
128 Tcp(String, u16),
130
131 TcpTls {
133 host: String,
135
136 port: u16,
138
139 insecure: bool,
148 },
149
150 Unix(PathBuf),
152}
153
154impl Default for ConnectionAddr {
155 fn default() -> Self {
156 Self::Tcp("127.0.0.1".to_string(), 6379)
157 }
158}
159
160impl From<ConnectionAddr> for redis::ConnectionAddr {
161 fn from(addr: ConnectionAddr) -> Self {
162 match addr {
163 ConnectionAddr::Tcp(host, port) => Self::Tcp(host, port),
164 ConnectionAddr::TcpTls {
165 host,
166 port,
167 insecure,
168 } => Self::TcpTls {
169 host,
170 port,
171 insecure,
172 },
173 ConnectionAddr::Unix(path) => Self::Unix(path),
174 }
175 }
176}
177
178impl From<redis::ConnectionAddr> for ConnectionAddr {
179 fn from(addr: redis::ConnectionAddr) -> Self {
180 match addr {
181 redis::ConnectionAddr::Tcp(host, port) => Self::Tcp(host, port),
182 redis::ConnectionAddr::TcpTls {
183 host,
184 port,
185 insecure,
186 } => ConnectionAddr::TcpTls {
187 host,
188 port,
189 insecure,
190 },
191 redis::ConnectionAddr::Unix(path) => Self::Unix(path),
192 }
193 }
194}
195
196#[derive(Clone, Debug, Default)]
200#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
201#[cfg_attr(feature = "serde", serde(crate = "serde_1"))]
202pub struct ConnectionInfo {
203 pub addr: ConnectionAddr,
205
206 #[cfg_attr(feature = "serde", serde(flatten))]
208 pub redis: RedisConnectionInfo,
209}
210
211impl From<ConnectionInfo> for redis::ConnectionInfo {
212 fn from(info: ConnectionInfo) -> Self {
213 Self {
214 addr: info.addr.into(),
215 redis: info.redis.into(),
216 }
217 }
218}
219
220impl From<redis::ConnectionInfo> for ConnectionInfo {
221 fn from(info: redis::ConnectionInfo) -> Self {
222 Self {
223 addr: info.addr.into(),
224 redis: info.redis.into(),
225 }
226 }
227}
228
229impl redis::IntoConnectionInfo for ConnectionInfo {
230 fn into_connection_info(self) -> RedisResult<redis::ConnectionInfo> {
231 Ok(self.into())
232 }
233}
234
235#[derive(Clone, Debug, Default)]
239#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
240#[cfg_attr(feature = "serde", serde(crate = "serde_1"))]
241pub struct RedisConnectionInfo {
242 pub db: i64,
244
245 pub username: Option<String>,
247
248 pub password: Option<String>,
250}
251
252impl From<RedisConnectionInfo> for redis::RedisConnectionInfo {
253 fn from(info: RedisConnectionInfo) -> Self {
254 Self {
255 db: info.db,
256 username: info.username,
257 password: info.password,
258 }
259 }
260}
261
262impl From<redis::RedisConnectionInfo> for RedisConnectionInfo {
263 fn from(info: redis::RedisConnectionInfo) -> Self {
264 Self {
265 db: info.db,
266 username: info.username,
267 password: info.password,
268 }
269 }
270}
271
272#[derive(Debug)]
274pub enum ConfigError {
275 UrlAndConnectionSpecified,
277 Redis(RedisError),
279}
280
281impl From<RedisError> for ConfigError {
282 fn from(e: RedisError) -> Self {
283 Self::Redis(e)
284 }
285}
286
287impl fmt::Display for ConfigError {
288 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289 match self {
290 Self::UrlAndConnectionSpecified => write!(
291 f,
292 "url and connection must not be specified at the same time."
293 ),
294 Self::Redis(e) => write!(f, "Redis: {}", e),
295 }
296 }
297}
298
299impl std::error::Error for ConfigError {}