Skip to main content

oracledb_protocol/
capabilities.rs

1#![forbid(unsafe_code)]
2
3use crate::{ProtocolError, Result, TNS_VERSION_DESIRED, TNS_VERSION_MIN_ACCEPTED};
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub struct TnsVersion(u16);
7
8impl TnsVersion {
9    pub fn negotiate(server_version: u16) -> Result<Self> {
10        // The refusal floor is TNS_VERSION_MIN_ACCEPTED (315, Oracle 12.1),
11        // not TNS_VERSION_MIN (300): the CONNECT packet advertises 300 like
12        // the reference, but the reference refuses any ACCEPT below 315
13        // (connect.pyx ERR_SERVER_VERSION_NOT_SUPPORTED). Oracle 11g answers
14        // with 314.
15        if server_version < TNS_VERSION_MIN_ACCEPTED {
16            return Err(ProtocolError::UnsupportedVersion {
17                version: server_version,
18                minimum: TNS_VERSION_MIN_ACCEPTED,
19            });
20        }
21
22        Ok(Self(server_version.min(TNS_VERSION_DESIRED)))
23    }
24
25    pub fn as_u16(self) -> u16 {
26        self.0
27    }
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn caps_high_versions_to_reference_desired_version() {
36        assert_eq!(
37            TnsVersion::negotiate(999)
38                .expect("999 should negotiate down to desired reference version")
39                .as_u16(),
40            TNS_VERSION_DESIRED
41        );
42    }
43
44    #[test]
45    fn rejects_versions_below_reference_floor() {
46        // 314 is exactly what Oracle 11g negotiates; the reference refuses
47        // anything below TNS_VERSION_MIN_ACCEPTED = 315 (12.1).
48        assert!(matches!(
49            TnsVersion::negotiate(TNS_VERSION_MIN_ACCEPTED - 1),
50            Err(ProtocolError::UnsupportedVersion {
51                version: 314,
52                minimum: 315,
53            })
54        ));
55        assert!(TnsVersion::negotiate(TNS_VERSION_MIN_ACCEPTED).is_ok());
56    }
57}