hdbconnect_impl/protocol/parts/
client_info.rs

1use crate::{
2    HdbResult,
3    protocol::parts::hdb_value::{emit_length_and_string, string_length},
4};
5use std::collections::HashMap;
6use std::env;
7use std::path::Path;
8
9#[derive(Clone, Debug)]
10pub(crate) struct ClientInfo(HashMap<ClientInfoKey, String>);
11
12impl Default for ClientInfo {
13    fn default() -> Self {
14        let mut ci = Self(HashMap::<ClientInfoKey, String>::new());
15
16        if let Some(os_str) = env::args_os().next() {
17            let p = Path::new(&os_str);
18            if let Some(s) = p.file_name() {
19                ci.set_application(s.to_string_lossy());
20            }
21        }
22        if cfg!(feature = "async") {
23            ci.set_driver("hdbconnect_async");
24            ci.set_driver_version(&format!("hdbconnect_impl = {}", env!("CARGO_PKG_VERSION")));
25            ci.set_driver_info("https://crates.io/crates/hdbconnect_async");
26        } else {
27            ci.set_driver("hdbconnect");
28            ci.set_driver_version(&format!("hdbconnect_impl = {}", env!("CARGO_PKG_VERSION")));
29            ci.set_driver_info("https://crates.io/crates/hdbconnect");
30        }
31
32        ci
33    }
34}
35
36impl std::fmt::Display for ClientInfo {
37    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
38        for (k, v) in &self.0 {
39            writeln!(f, "{k:?} = {v}")?;
40        }
41        Ok(())
42    }
43}
44
45impl ClientInfo {
46    pub fn set_application<S: AsRef<str>>(&mut self, application: S) {
47        self.set(ClientInfoKey::Application, application.as_ref());
48    }
49    pub fn set_application_version(&mut self, application_version: &str) {
50        self.set(ClientInfoKey::ApplicationVersion, application_version);
51    }
52    pub fn set_application_source(&mut self, application_source: &str) {
53        self.set(ClientInfoKey::ApplicationSource, application_source);
54    }
55    pub fn set_application_user(&mut self, application_user: &str) {
56        self.set(ClientInfoKey::ApplicationUser, application_user);
57    }
58    fn set_driver(&mut self, driver: &str) {
59        self.set(ClientInfoKey::Driver, driver);
60    }
61    fn set_driver_info(&mut self, driver_info: &str) {
62        self.set(ClientInfoKey::DriverInfo, driver_info);
63    }
64    fn set_driver_version(&mut self, driver_version: &str) {
65        self.set(ClientInfoKey::DriverVersion, driver_version);
66    }
67
68    pub fn emit(&self, w: &mut dyn std::io::Write) -> HdbResult<()> {
69        for (key, value) in &self.0 {
70            emit_length_and_string(key, w)?;
71            emit_length_and_string(value, w)?;
72        }
73        Ok(())
74    }
75
76    pub fn size(&self) -> usize {
77        let mut len = 0;
78        for (key, value) in &self.0 {
79            len += string_length(key) + string_length(value);
80        }
81        len
82    }
83    pub fn count(&self) -> usize {
84        self.0.len() * 2
85    }
86
87    fn set(&mut self, key: ClientInfoKey, value: &str) {
88        let value = value.to_string();
89        self.0.insert(key, value);
90    }
91}
92
93#[derive(Clone, Debug, Eq, Hash, PartialEq)]
94enum ClientInfoKey {
95    Application,
96    ApplicationVersion,
97    ApplicationSource,
98    ApplicationUser,
99    Driver,
100    DriverInfo,
101    DriverVersion,
102}
103impl AsRef<str> for ClientInfoKey {
104    fn as_ref(&self) -> &str {
105        match &self {
106            Self::Application => "APPLICATION",
107            Self::ApplicationVersion => "APPLICATIONVERSION",
108            Self::ApplicationSource => "APPLICATIONSOURCE",
109            Self::ApplicationUser => "APPLICATIONUSER",
110            Self::Driver => "DRIVER",
111            Self::DriverInfo => "DRIVERINFO",
112            Self::DriverVersion => "DRIVERVERSION",
113        }
114    }
115}