odbc_sys/
handles.rs

1use std::{ffi::c_void, ptr::null_mut};
2
3// ODBC handles are pointers to opaque C types. We do not know their memory layout or other details
4// of their implementation. This RFC suggest how to represent them in Rust:
5// <https://rust-lang.github.io/rfcs/1861-extern-types.html>
6//
7// Until this is stable we could choose to represent them like suggested in the nomicon:
8// <https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs>
9//
10// However, we know in the context of ODBC that we are always interested in the *mut versions of
11// this pointer. For now a strict alias around `*mut c_void` seems to be the most pragmatic
12// solution.
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[repr(transparent)]
16pub struct Handle(pub *mut c_void);
17
18impl Handle {
19    pub fn null() -> Self {
20        Self(null_mut())
21    }
22
23    pub fn as_henv(self) -> HEnv {
24        HEnv(self.0)
25    }
26
27    pub fn as_hdbc(self) -> HDbc {
28        HDbc(self.0)
29    }
30
31    pub fn as_hstmt(self) -> HStmt {
32        HStmt(self.0)
33    }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37#[repr(transparent)]
38pub struct HEnv(pub *mut c_void);
39
40impl HEnv {
41    pub fn null() -> Self {
42        Self(null_mut())
43    }
44
45    pub fn as_handle(self) -> Handle {
46        Handle(self.0)
47    }
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51#[repr(transparent)]
52pub struct HDesc(pub *mut c_void);
53
54impl HDesc {
55    pub fn null() -> Self {
56        Self(null_mut())
57    }
58}
59
60/// The connection handle references storage of all information about the connection to the data
61/// source, including status, transaction state, and error information.
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63#[repr(transparent)]
64pub struct HDbc(pub *mut c_void);
65
66impl HDbc {
67    pub fn as_handle(self) -> Handle {
68        Handle(self.0)
69    }
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73#[repr(transparent)]
74pub struct HStmt(pub *mut c_void);
75
76impl HStmt {
77    pub fn as_handle(self) -> Handle {
78        Handle(self.0)
79    }
80}
81
82// Handles are `Send` according to ODBC spec, since they must be able to be used from different
83// threads. They even must protect their inner state. This would also make them `Sync`, yet they do
84// have interior mutability for error handling.
85// See: <https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/multithreading>
86
87unsafe impl Send for HEnv {}
88
89unsafe impl Send for HDbc {}
90
91unsafe impl Send for HStmt {}