1use core::fmt;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct TdsVersion(u32);
11
12impl TdsVersion {
13 pub const V7_0: Self = Self(0x70000000);
15
16 pub const V7_1: Self = Self(0x71000000);
18
19 pub const V7_1_REV1: Self = Self(0x71000001);
21
22 pub const V7_2: Self = Self(0x72090002);
24
25 pub const V7_3A: Self = Self(0x730A0003);
27
28 pub const V7_3B: Self = Self(0x730B0003);
30
31 pub const V7_4: Self = Self(0x74000004);
33
34 pub const V8_0: Self = Self(0x08000000);
36
37 #[must_use]
39 pub const fn new(version: u32) -> Self {
40 Self(version)
41 }
42
43 #[must_use]
45 pub const fn raw(self) -> u32 {
46 self.0
47 }
48
49 #[must_use]
51 pub const fn is_tds_8(self) -> bool {
52 self.0 == Self::V8_0.0
54 }
55
56 #[must_use]
61 pub const fn requires_prelogin_encryption_negotiation(self) -> bool {
62 !self.is_tds_8()
63 }
64
65 #[must_use]
67 pub const fn major(self) -> u8 {
68 if self.is_tds_8() {
69 8
70 } else {
71 ((self.0 >> 24) & 0xFF) as u8
72 }
73 }
74
75 #[must_use]
77 pub const fn minor(self) -> u8 {
78 if self.is_tds_8() {
79 0
80 } else {
81 ((self.0 >> 16) & 0xFF) as u8
82 }
83 }
84}
85
86impl Default for TdsVersion {
87 fn default() -> Self {
88 Self::V7_4
89 }
90}
91
92impl fmt::Display for TdsVersion {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 if self.is_tds_8() {
95 write!(f, "TDS 8.0")
96 } else {
97 write!(f, "TDS {}.{}", self.major(), self.minor())
98 }
99 }
100}
101
102impl From<u32> for TdsVersion {
103 fn from(value: u32) -> Self {
104 Self(value)
105 }
106}
107
108impl From<TdsVersion> for u32 {
109 fn from(version: TdsVersion) -> Self {
110 version.0
111 }
112}
113
114#[cfg(test)]
115#[allow(clippy::unwrap_used)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_version_comparison() {
121 assert!(TdsVersion::V7_4 > TdsVersion::V7_3B);
122 assert!(TdsVersion::V7_3B > TdsVersion::V7_3A);
123 }
124
125 #[test]
126 fn test_tds_8_detection() {
127 assert!(TdsVersion::V8_0.is_tds_8());
128 assert!(!TdsVersion::V7_4.is_tds_8());
129 }
130
131 #[test]
132 fn test_prelogin_requirement() {
133 assert!(TdsVersion::V7_4.requires_prelogin_encryption_negotiation());
134 assert!(!TdsVersion::V8_0.requires_prelogin_encryption_negotiation());
135 }
136}