Skip to main content

paper_client/
error.rs

1/*
2 * Copyright (c) Kia Shakiba
3 *
4 * This source code is licensed under the GNU AGPLv3 license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8use std::io::Read;
9
10#[cfg(feature = "tokio")]
11use paper_utils::stream::AsyncStreamReader;
12use paper_utils::stream::StreamReader;
13use thiserror::Error;
14#[cfg(feature = "tokio")]
15use tokio::io::AsyncRead;
16
17pub type PaperClientResult<T> = Result<T, PaperClientError>;
18
19#[derive(Debug, PartialEq, Error)]
20pub enum PaperClientError {
21	#[error(transparent)]
22	ServerError(#[from] PaperServerError),
23
24	#[error(transparent)]
25	CacheError(#[from] PaperCacheError),
26
27	#[error("invalid PaperCache address")]
28	InvalidAddress,
29
30	#[error("could not connect to PaperServer")]
31	UnreachableServer,
32
33	#[error("could not send command to PaperServer")]
34	InvalidCommand,
35
36	#[error("could not parse supplied value as PaperValue")]
37	InvalidValue,
38
39	#[error("could not receive response from PaperServer")]
40	InvalidResponse,
41
42	#[error("an internal error occurred")]
43	Internal,
44
45	#[error("disconnected from PaperServer")]
46	Disconnected,
47}
48
49#[derive(Debug, PartialEq, Error)]
50pub enum PaperCacheError {
51	#[error("an internal error occurred")]
52	Internal,
53
54	#[error("the key was not found in the cache")]
55	KeyNotFound,
56
57	#[error("the value size cannot be zero")]
58	ZeroValueSize,
59
60	#[error("the value size cannot exceed the cache size")]
61	ExceedingValueSize,
62
63	#[error("the cache size cannot be zero")]
64	ZeroCacheSize,
65
66	#[error("unconfigured policy")]
67	UnconfiguredPolicy,
68
69	#[error("invalid policy")]
70	InvalidPolicy,
71}
72
73#[derive(Debug, PartialEq, Error)]
74pub enum PaperServerError {
75	#[error("an internal error occurred")]
76	Internal,
77
78	#[error("the maximum number of connections was exceeded")]
79	MaxConnectionsExceeded,
80
81	#[error("unauthorized")]
82	Unauthorized,
83}
84
85impl PaperClientError {
86	pub fn from_reader<R>(mut reader: StreamReader<R>) -> Self
87	where
88		R: Read,
89	{
90		let Ok(code) = reader.read_u8() else {
91			return PaperClientError::InvalidResponse;
92		};
93
94		if code == 0 {
95			let Ok(cache_code) = reader.read_u8() else {
96				return PaperClientError::InvalidResponse;
97			};
98
99			let cache_error = PaperCacheError::from_code(cache_code);
100
101			return PaperClientError::CacheError(cache_error);
102		}
103
104		let server_error = PaperServerError::from_code(code);
105		PaperClientError::ServerError(server_error)
106	}
107
108	#[cfg(feature = "tokio")]
109	pub async fn from_reader_async<R>(mut reader: AsyncStreamReader<'_, R>) -> Self
110	where
111		R: AsyncRead + Unpin,
112	{
113		let Ok(code) = reader.read_u8().await else {
114			return PaperClientError::InvalidResponse;
115		};
116
117		if code == 0 {
118			let Ok(cache_code) = reader.read_u8().await else {
119				return PaperClientError::InvalidResponse;
120			};
121
122			let cache_error = PaperCacheError::from_code(cache_code);
123
124			return PaperClientError::CacheError(cache_error);
125		}
126
127		let server_error = PaperServerError::from_code(code);
128		PaperClientError::ServerError(server_error)
129	}
130}
131
132impl PaperServerError {
133	fn from_code(code: u8) -> Self {
134		match code {
135			2 => PaperServerError::MaxConnectionsExceeded,
136			3 => PaperServerError::Unauthorized,
137
138			_ => PaperServerError::Internal,
139		}
140	}
141}
142
143impl PaperCacheError {
144	fn from_code(code: u8) -> Self {
145		match code {
146			1 => PaperCacheError::KeyNotFound,
147
148			2 => PaperCacheError::ZeroValueSize,
149			3 => PaperCacheError::ExceedingValueSize,
150
151			4 => PaperCacheError::ZeroCacheSize,
152
153			5 => PaperCacheError::UnconfiguredPolicy,
154			6 => PaperCacheError::InvalidPolicy,
155
156			_ => PaperCacheError::Internal,
157		}
158	}
159}