1use crate::error::Error;
5use crate::error::Error::OperationCancelledError;
6use futures::FutureExt;
7use futures::future::Either;
8use std::future::Future;
9use std::path::PathBuf;
10use tokio_util::sync::CancellationToken;
11
12pub type TdsResult<T> = Result<T, Error>;
14
15pub const TDS_8_ALPN_PROTOCOL: &str = "tds/8.0";
17
18#[derive(Debug)]
23pub struct CancelHandle {
24 pub(crate) cancel_token: CancellationToken,
25}
26
27impl CancelHandle {
28 pub fn new() -> Self {
30 CancelHandle {
31 cancel_token: CancellationToken::new(),
32 }
33 }
34
35 pub fn cancel(self) {
37 self.cancel_token.cancel();
38 }
39
40 pub fn child_handle(&self) -> Self {
42 Self::from(self.cancel_token.child_token())
43 }
44
45 pub(crate) fn run_until_cancelled<'a, F, ResultType>(
46 cancel_handle: Option<&'a CancelHandle>,
47 f: F,
48 ) -> impl Future<Output = F::Output> + Send + 'a
49 where
50 F: Future<Output = TdsResult<ResultType>> + Send + 'a,
51 {
52 match cancel_handle {
53 Some(handle) => Either::Left(handle.cancel_token.run_until_cancelled(f).map(
54 |result| match result {
55 Some(result) => result,
56 None => Err(OperationCancelledError("Request was cancelled".to_string())),
57 },
58 )),
59 None => Either::Right(f),
60 }
61 }
62}
63
64impl From<CancellationToken> for CancelHandle {
65 fn from(value: CancellationToken) -> Self {
66 CancelHandle {
67 cancel_token: value,
68 }
69 }
70}
71
72impl Default for CancelHandle {
73 fn default() -> Self {
74 Self::new()
75 }
76}
77
78#[derive(PartialEq, Debug)]
80pub enum SQLServerVersion {
81 SqlServerNotsupported = 0,
83 SqlServer2000 = 8,
85 SqlServer2005 = 9,
87 SqlServer2008 = 10,
89 SqlServer2012 = 11,
91 SqlServer2014 = 12,
93 SqlServer2016 = 13,
95 SqlServer2017 = 14,
97 SqlServer2019 = 15,
99 SqlServer2022 = 16,
101 SqlServer2022lus = 17,
103}
104
105impl From<u8> for SQLServerVersion {
106 fn from(v: u8) -> Self {
107 match v {
108 0 => SQLServerVersion::SqlServerNotsupported,
109 8 => SQLServerVersion::SqlServer2000,
110 9 => SQLServerVersion::SqlServer2005,
111 10 => SQLServerVersion::SqlServer2008,
112 11 => SQLServerVersion::SqlServer2012,
113 12 => SQLServerVersion::SqlServer2014,
114 13 => SQLServerVersion::SqlServer2016,
115 14 => SQLServerVersion::SqlServer2017,
116 15 => SQLServerVersion::SqlServer2019,
117 16 => SQLServerVersion::SqlServer2022,
118 17 => SQLServerVersion::SqlServer2022lus,
119 _ => SQLServerVersion::SqlServerNotsupported,
120 }
121 }
122}
123
124#[derive(Clone, Copy, PartialEq, Debug)]
126pub struct Version {
127 pub major: u8,
129 pub minor: u8,
131 pub build: u16,
133 pub revision: u16,
135}
136
137impl Version {
138 pub fn new(major: u8, minor: u8, build: u16, revision: u16) -> Self {
140 Version {
141 major,
142 minor,
143 build,
144 revision,
145 }
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[test]
154 fn sql_server_version_from_known_values() {
155 assert_eq!(
156 SQLServerVersion::from(0),
157 SQLServerVersion::SqlServerNotsupported
158 );
159 assert_eq!(SQLServerVersion::from(8), SQLServerVersion::SqlServer2000);
160 assert_eq!(SQLServerVersion::from(9), SQLServerVersion::SqlServer2005);
161 assert_eq!(SQLServerVersion::from(10), SQLServerVersion::SqlServer2008);
162 assert_eq!(SQLServerVersion::from(11), SQLServerVersion::SqlServer2012);
163 assert_eq!(SQLServerVersion::from(12), SQLServerVersion::SqlServer2014);
164 assert_eq!(SQLServerVersion::from(13), SQLServerVersion::SqlServer2016);
165 assert_eq!(SQLServerVersion::from(14), SQLServerVersion::SqlServer2017);
166 assert_eq!(SQLServerVersion::from(15), SQLServerVersion::SqlServer2019);
167 assert_eq!(SQLServerVersion::from(16), SQLServerVersion::SqlServer2022);
168 assert_eq!(
169 SQLServerVersion::from(17),
170 SQLServerVersion::SqlServer2022lus
171 );
172 }
173
174 #[test]
175 fn sql_server_version_from_unknown_defaults_to_not_supported() {
176 assert_eq!(
177 SQLServerVersion::from(1),
178 SQLServerVersion::SqlServerNotsupported
179 );
180 assert_eq!(
181 SQLServerVersion::from(7),
182 SQLServerVersion::SqlServerNotsupported
183 );
184 assert_eq!(
185 SQLServerVersion::from(18),
186 SQLServerVersion::SqlServerNotsupported
187 );
188 assert_eq!(
189 SQLServerVersion::from(255),
190 SQLServerVersion::SqlServerNotsupported
191 );
192 }
193
194 #[test]
195 fn cancel_handle_default() {
196 let handle = CancelHandle::default();
197 assert!(!handle.cancel_token.is_cancelled());
198 }
199
200 #[tokio::test]
201 async fn run_until_cancelled_none_handle() {
202 let result: TdsResult<i32> =
203 CancelHandle::run_until_cancelled(None, async { Ok(42) }).await;
204 assert_eq!(result.unwrap(), 42);
205 }
206
207 #[tokio::test]
208 async fn run_until_cancelled_with_handle_completes() {
209 let handle = CancelHandle::new();
210 let result: TdsResult<i32> =
211 CancelHandle::run_until_cancelled(Some(&handle), async { Ok(99) }).await;
212 assert_eq!(result.unwrap(), 99);
213 }
214
215 #[tokio::test]
216 async fn run_until_cancelled_with_cancelled_handle_stops_pending_future() {
217 let handle = CancelHandle::new();
218 handle.cancel_token.cancel();
219
220 let result = CancelHandle::run_until_cancelled(
221 Some(&handle),
222 std::future::pending::<TdsResult<i32>>(),
223 )
224 .await;
225
226 assert!(matches!(result, Err(OperationCancelledError(_))));
227 }
228}
229
230#[derive(Clone, PartialEq, Debug)]
232pub struct EncryptionOptions {
233 pub mode: EncryptionSetting,
235 pub trust_server_certificate: bool,
237 pub host_name_in_cert: Option<String>,
239 pub server_certificate: Option<PathBuf>,
243}
244
245impl EncryptionOptions {
246 pub fn new() -> Self {
248 EncryptionOptions {
249 mode: EncryptionSetting::Strict,
250 trust_server_certificate: false,
251 host_name_in_cert: None,
252 server_certificate: None,
253 }
254 }
255}
256
257impl Default for EncryptionOptions {
258 fn default() -> Self {
259 Self::new()
260 }
261}
262
263#[derive(Clone, Copy, PartialEq, Debug)]
265pub enum EncryptionSetting {
266 PreferOff,
268 On,
270 Required,
272 Strict,
274}
275
276#[derive(Clone, Copy, PartialEq, Debug)]
277pub(crate) enum NegotiatedEncryptionSetting {
278 Strict,
279 LoginOnly,
280 Mandatory,
281 NoEncryption,
282}