1use super::branding::*;
2use crate::{gel::BuildPhase, host::HostParseError};
3use std::{convert::Infallible, num::ParseIntError};
4
5use super::ParamSource;
6
7#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display, PartialOrd, Ord)]
8pub enum CompoundSource {
9 #[display("DSN")]
10 Dsn,
11 #[display("Instance")]
12 Instance,
13 #[display("Credentials file")]
14 CredentialsFile,
15 #[display("Host and port")]
16 HostPort,
17 #[display("Unix socket")]
18 UnixSocket,
19}
20
21#[derive(
22 Debug, Clone, PartialEq, Eq, derive_more::Display, derive_more::Error, PartialOrd, Ord,
23)]
24pub enum TlsSecurityError {
25 IncompatibleSecurityOptions,
26 InvalidValue,
27}
28
29#[derive(
30 Debug, Clone, PartialEq, Eq, derive_more::Display, derive_more::Error, PartialOrd, Ord,
31)]
32pub enum InstanceNameError {
33 InvalidInstanceName,
34 InvalidCloudOrgName,
35 InvalidCloudInstanceName,
36}
37
38#[derive(
39 Debug, Clone, PartialEq, Eq, derive_more::Display, derive_more::Error, PartialOrd, Ord,
40)]
41#[error(ignore)]
42pub enum InvalidCredentialsFileError {
43 FileNotFound,
44 #[display("{}={}, {}={}", _0.0, _0.1, _1.0, _1.1)]
45 ConflictingSettings((String, String), (String, String)),
46 SerializationError(String),
47}
48
49#[derive(
50 Debug, Clone, PartialEq, Eq, derive_more::Display, derive_more::Error, PartialOrd, Ord,
51)]
52pub enum InvalidSecretKeyError {
53 InvalidJwt,
54 MissingIssuer,
55}
56
57#[derive(
58 Debug, Clone, PartialEq, Eq, derive_more::Display, derive_more::Error, PartialOrd, Ord,
59)]
60pub enum InvalidDsnError {
61 InvalidScheme,
62 ParseError,
63 DuplicateOptions(#[error(not(source))] String),
64 BranchAndDatabase,
65}
66
67#[derive(
74 Debug,
75 derive_more::Error,
76 derive_more::Display,
77 derive_more::From,
78 PartialEq,
79 Eq,
80 PartialOrd,
81 Ord,
82)]
83pub enum ParseError {
84 #[display("Credentials file not found")]
85 CredentialsFileNotFound,
86 #[display("Environment variable was not set: {_1} (from {_0})")]
87 EnvNotFound(ParamSource, String),
88 #[display("{_0} and {_1} are mutually exclusive and cannot be used together")]
89 ExclusiveOptions(String, String),
90 #[display("File not found")]
91 FileNotFound,
92 #[display("Invalid credentials file: {_0}")]
93 #[from]
94 InvalidCredentialsFile(InvalidCredentialsFileError),
95 #[display("Invalid database")]
96 InvalidDatabase,
97 #[display("Invalid DSN: {_0}")]
98 #[from]
99 InvalidDsn(InvalidDsnError),
100 #[display("Invalid DSN or instance name")]
101 InvalidDsnOrInstanceName,
102 #[display("Invalid host")]
103 InvalidHost,
104 #[display("Invalid instance name: {_0}")]
105 #[from]
106 InvalidInstanceName(InstanceNameError),
107 #[display("Invalid port")]
108 InvalidPort,
109 #[display("Invalid secret key")]
110 #[from]
111 InvalidSecretKey(InvalidSecretKeyError),
112 #[display("Invalid TLS security")]
113 #[from]
114 InvalidTlsSecurity(TlsSecurityError),
115 #[display("Invalid user")]
116 InvalidUser,
117 #[display("Invalid certificate")]
118 InvalidCertificate,
119 #[display("Invalid duration")]
120 InvalidDuration,
121 #[display("Multiple compound options were specified while parsing {_0}: {_1:#?}")]
122 MultipleCompound(BuildPhase, #[error(not(source))] Vec<CompoundSource>),
123 #[display("No connection options specified, and no project manifest file found ({MANIFEST_FILE_DISPLAY_NAME})")]
124 NoOptionsOrToml,
125 #[display("Project not initialized")]
126 ProjectNotInitialised,
127 #[display("Secret key not found")]
128 SecretKeyNotFound,
129 #[display("Unix socket unsupported")]
130 UnixSocketUnsupported,
131}
132
133impl ParseError {
134 pub fn error_type(&self) -> &str {
135 match self {
136 Self::EnvNotFound(..) => "env_not_found",
137 Self::CredentialsFileNotFound => "credentials_file_not_found",
138 Self::ExclusiveOptions(..) => "exclusive_options",
139 Self::FileNotFound => "file_not_found",
140 Self::InvalidCredentialsFile(_) => "invalid_credentials_file",
141 Self::InvalidDatabase => "invalid_database",
142 Self::InvalidDsn(_) => "invalid_dsn",
143 Self::InvalidDsnOrInstanceName => "invalid_dsn_or_instance_name",
144 Self::InvalidHost => "invalid_host",
145 Self::InvalidInstanceName(_) => "invalid_instance_name",
146 Self::InvalidPort => "invalid_port",
147 Self::InvalidSecretKey(_) => "invalid_secret_key",
148 Self::InvalidTlsSecurity(_) => "invalid_tls_security",
149 Self::InvalidUser => "invalid_user",
150 Self::InvalidCertificate => "invalid_certificate",
151 Self::InvalidDuration => "invalid_duration",
152 Self::MultipleCompound(BuildPhase::Environment, _) => "multiple_compound_env",
153 Self::MultipleCompound(BuildPhase::Options, _) => "multiple_compound_opts",
154 Self::MultipleCompound(BuildPhase::Project, _) => "multiple_compound_project",
155 Self::NoOptionsOrToml => "no_options_or_toml",
156 Self::ProjectNotInitialised => "project_not_initialised",
157 Self::SecretKeyNotFound => "secret_key_not_found",
158 Self::UnixSocketUnsupported => "unix_socket_unsupported",
159 }
160 }
161
162 pub fn gel_error(self) -> gel_errors::Error {
163 use gel_errors::ErrorKind;
164
165 match self {
166 Self::EnvNotFound(..)
167 | Self::CredentialsFileNotFound
168 | Self::FileNotFound
169 | Self::InvalidCredentialsFile(_)
170 | Self::InvalidDatabase
171 | Self::InvalidDsn(_)
172 | Self::InvalidDsnOrInstanceName
173 | Self::InvalidHost
174 | Self::InvalidInstanceName(_)
175 | Self::InvalidPort
176 | Self::InvalidSecretKey(_)
177 | Self::InvalidTlsSecurity(_)
178 | Self::InvalidUser
179 | Self::InvalidCertificate
180 | Self::InvalidDuration
181 | Self::UnixSocketUnsupported => {
182 gel_errors::InvalidArgumentError::with_source(self)
184 }
185 Self::MultipleCompound(..) | Self::ExclusiveOptions(..) => {
186 gel_errors::InterfaceError::with_source(self)
188 }
189 Self::NoOptionsOrToml | Self::ProjectNotInitialised => {
190 gel_errors::ClientNoCredentialsError::with_source(self)
192 }
193 Self::SecretKeyNotFound => {
194 gel_errors::NoCloudConfigFound::with_source(self)
196 }
197 }
198 }
199}
200
201impl From<ParseError> for gel_errors::Error {
202 fn from(val: ParseError) -> Self {
203 val.gel_error()
204 }
205}
206
207impl From<ParseIntError> for ParseError {
208 fn from(_: ParseIntError) -> Self {
209 ParseError::InvalidPort
210 }
211}
212
213impl From<HostParseError> for ParseError {
214 fn from(_: HostParseError) -> Self {
215 ParseError::InvalidHost
216 }
217}
218
219impl From<Infallible> for ParseError {
220 fn from(_: Infallible) -> Self {
221 unreachable!()
222 }
223}
224
225#[derive(Debug, Clone, PartialEq, Eq, derive_more::Display, PartialOrd, Ord)]
226pub enum Warning {
227 #[display("Deprecated credential property: {_0}")]
228 DeprecatedCredentialProperty(String),
229 #[display("Deprecated environment variable: {_0}")]
230 DeprecatedEnvironmentVariable(String, String),
231 #[display("Multiple environment variables set: {}", _0.join(", "))]
232 MultipleEnvironmentVariables(Vec<String>),
233 #[display("{_0} is ignored when using Docker TCP port")]
234 DockerPortIgnored(String),
235 #[display("Database and branch are set to default values")]
236 DefaultDatabaseAndBranch,
237 #[display("Updated out-of-date credentials file")]
238 UpdatedOutdatedCredentials,
239}
240
241#[derive(Debug, Default)]
242pub struct Warnings {
243 warnings: Vec<Warning>,
244}
245
246impl Warnings {
247 pub fn warn(&mut self, warning: Warning) {
248 self.warnings.push(warning);
249 }
250
251 pub fn into_vec(self) -> Vec<Warning> {
252 self.warnings
253 }
254
255 pub fn iter(&self) -> impl Iterator<Item = &Warning> {
256 self.warnings.iter()
257 }
258}
259
260impl<'a> IntoIterator for &'a Warnings {
261 type Item = &'a Warning;
262
263 type IntoIter = std::slice::Iter<'a, Warning>;
264
265 fn into_iter(self) -> Self::IntoIter {
266 self.warnings.iter()
267 }
268}