odbc_api/buffers/
indicator.rs

1use odbc_sys::{NO_TOTAL, NULL_DATA};
2
3/// Indicates existence and length of a value.
4#[derive(Debug, PartialEq, Eq, Clone, Copy)]
5pub enum Indicator {
6    /// Field does not exist
7    Null,
8    /// Field exists, but its length had not be reported by the driver.
9    NoTotal,
10    /// Fields exists. Value indicates number of bytes required to store the value. In case of
11    /// truncated data, this is the true length of the data, before truncation occurred.
12    Length(usize),
13}
14
15impl Indicator {
16    /// Creates an indicator from an `isize` indicator value returned by ODBC. Users of this crate
17    /// have likely no need to call this method.
18    pub fn from_isize(indicator: isize) -> Self {
19        match indicator {
20            NULL_DATA => Indicator::Null,
21            NO_TOTAL => Indicator::NoTotal,
22            other => Indicator::Length(other.try_into().expect(
23                "Length indicator must be non-negative. This is not necessarily a programming \
24                error, in the application. If you are on a 64Bit platfrom and the isize value has \
25                been returned by the driver there may be a better exlpanation for what went wrong: \
26                In the past some driver managers and drivers assumed SQLLEN to be 32Bits even on \
27                64Bit platforms. Please ask your vendor for a version of the driver which is \
28                correctly build using 64Bits for SQLLEN.",
29            )),
30        }
31    }
32
33    /// Creates an indicator value as required by the ODBC C API.
34    pub fn to_isize(self) -> isize {
35        match self {
36            Indicator::Null => NULL_DATA,
37            Indicator::NoTotal => NO_TOTAL,
38            Indicator::Length(len) => len.try_into().unwrap(),
39        }
40    }
41
42    /// Does this indicator imply truncation for a value of the given length?
43    ///
44    /// `length_in_buffer` is specified in bytes without terminating zeroes.
45    pub fn is_truncated(self, length_in_buffer: usize) -> bool {
46        match self {
47            Indicator::Null => false,
48            Indicator::NoTotal => true,
49            Indicator::Length(complete_length) => complete_length > length_in_buffer,
50        }
51    }
52
53    /// Only `true` if the indicator is the equivalent to [`odbc_sys::NULL_DATA`], indicating a
54    /// non-existing value.
55    pub fn is_null(self) -> bool {
56        match self {
57            Indicator::Null => true,
58            Indicator::NoTotal | Indicator::Length(_) => false,
59        }
60    }
61
62    /// If the indicator is [`Indicator::Length`] this is [`Some`].
63    pub fn length(self) -> Option<usize> {
64        if let Indicator::Length(len) = self {
65            Some(len)
66        } else {
67            None
68        }
69    }
70}