pgwire_lite/
value.rs

1// src/value.rs
2
3use std::fmt;
4
5/// Represents a value from a PostgreSQL query result.
6///
7/// This enum provides type-safe access to various PostgreSQL data types
8/// and includes conversion methods for common Rust types.
9#[derive(Debug, Clone, Default)]
10pub enum Value {
11    #[default]
12    Null,
13    Bool(bool),
14    Integer(i64),
15    Float(f64),
16    String(String),
17    Bytes(Vec<u8>),
18}
19
20impl fmt::Display for Value {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        match self {
23            Value::Null => write!(f, "NULL"),
24            Value::Bool(b) => write!(f, "{}", b),
25            Value::Integer(i) => write!(f, "{}", i),
26            Value::Float(fl) => write!(f, "{}", fl),
27            Value::String(s) => write!(f, "{}", s),
28            Value::Bytes(b) => write!(f, "{:?}", b),
29        }
30    }
31}
32
33// Default implementation for Value is Null
34
35// Implement From traits for common types
36impl From<String> for Value {
37    fn from(s: String) -> Self {
38        Value::String(s)
39    }
40}
41
42impl From<&str> for Value {
43    fn from(s: &str) -> Self {
44        Value::String(s.to_string())
45    }
46}
47
48impl From<bool> for Value {
49    fn from(b: bool) -> Self {
50        Value::Bool(b)
51    }
52}
53
54impl From<i64> for Value {
55    fn from(i: i64) -> Self {
56        Value::Integer(i)
57    }
58}
59
60impl From<i32> for Value {
61    fn from(i: i32) -> Self {
62        Value::Integer(i as i64)
63    }
64}
65
66impl From<f64> for Value {
67    fn from(f: f64) -> Self {
68        Value::Float(f)
69    }
70}
71
72impl From<Vec<u8>> for Value {
73    fn from(b: Vec<u8>) -> Self {
74        Value::Bytes(b)
75    }
76}
77
78// Try-conversion traits for getting values out
79impl Value {
80    /// Try to get the value as a string reference.
81    ///
82    /// Returns `None` if the value is not a String.
83    ///
84    /// # Example
85    ///
86    /// ```
87    /// use pgwire_lite::Value;
88    ///
89    /// let val = Value::from("hello");
90    /// assert_eq!(val.as_str(), Some("hello"));
91    ///
92    /// let val = Value::Integer(42);
93    /// assert_eq!(val.as_str(), None);
94    /// ```
95    pub fn as_str(&self) -> Option<&str> {
96        match self {
97            Value::String(s) => Some(s),
98            _ => None,
99        }
100    }
101
102    /// Try to get the value as a boolean.
103    ///
104    /// Returns `Some(bool)` if the value is a boolean or a string that can be
105    /// interpreted as a boolean (e.g., "true", "yes", "1").
106    /// Returns `None` for other types or strings that cannot be parsed as booleans.
107    ///
108    /// # Example
109    ///
110    /// ```
111    /// use pgwire_lite::Value;
112    ///
113    /// let val = Value::Bool(true);
114    /// assert_eq!(val.as_bool(), Some(true));
115    ///
116    /// let val = Value::from("yes");
117    /// assert_eq!(val.as_bool(), Some(true));
118    ///
119    /// let val = Value::from("0");
120    /// assert_eq!(val.as_bool(), Some(false));
121    ///
122    /// let val = Value::from("invalid");
123    /// assert_eq!(val.as_bool(), None);
124    /// ```
125    pub fn as_bool(&self) -> Option<bool> {
126        match self {
127            Value::Bool(b) => Some(*b),
128            Value::String(s) => match s.to_lowercase().as_str() {
129                "true" | "t" | "yes" | "y" | "1" => Some(true),
130                "false" | "f" | "no" | "n" | "0" => Some(false),
131                _ => None,
132            },
133            _ => None,
134        }
135    }
136
137    /// Try to get the value as a 64-bit signed integer.
138    ///
139    /// Returns `Some(i64)` if the value is an integer, a float that can be
140    /// converted to an integer, or a string that can be parsed as an integer.
141    /// Returns `None` for other types or values that cannot be converted.
142    ///
143    /// # Example
144    ///
145    /// ```
146    /// use pgwire_lite::Value;
147    ///
148    /// let val = Value::Integer(42);
149    /// assert_eq!(val.as_i64(), Some(42));
150    ///
151    /// let val = Value::Float(42.0);
152    /// assert_eq!(val.as_i64(), Some(42));
153    ///
154    /// let val = Value::from("42");
155    /// assert_eq!(val.as_i64(), Some(42));
156    ///
157    /// let val = Value::from("invalid");
158    /// assert_eq!(val.as_i64(), None);
159    /// ```
160    pub fn as_i64(&self) -> Option<i64> {
161        match self {
162            Value::Integer(i) => Some(*i),
163            Value::Float(f) => Some(*f as i64),
164            Value::String(s) => s.parse::<i64>().ok(),
165            _ => None,
166        }
167    }
168
169    /// Try to get the value as a 64-bit floating point number.
170    ///
171    /// Returns `Some(f64)` if the value is a float, an integer, or a string
172    /// that can be parsed as a float.
173    /// Returns `None` for other types or values that cannot be converted.
174    ///
175    /// # Example
176    ///
177    /// ```
178    /// use pgwire_lite::Value;
179    ///
180    /// let val = Value::Float(3.14);
181    /// assert_eq!(val.as_f64(), Some(3.14));
182    ///
183    /// let val = Value::Integer(42);
184    /// assert_eq!(val.as_f64(), Some(42.0));
185    ///
186    /// let val = Value::from("3.14");
187    /// assert_eq!(val.as_f64(), Some(3.14));
188    ///
189    /// let val = Value::from("invalid");
190    /// assert_eq!(val.as_f64(), None);
191    /// ```
192    pub fn as_f64(&self) -> Option<f64> {
193        match self {
194            Value::Float(f) => Some(*f),
195            Value::Integer(i) => Some(*i as f64),
196            Value::String(s) => s.parse::<f64>().ok(),
197            _ => None,
198        }
199    }
200
201    /// Check if the value is NULL.
202    ///
203    /// # Example
204    ///
205    /// ```
206    /// use pgwire_lite::Value;
207    ///
208    /// let val = Value::Null;
209    /// assert!(val.is_null());
210    ///
211    /// let val = Value::Integer(42);
212    /// assert!(!val.is_null());
213    /// ```
214    pub fn is_null(&self) -> bool {
215        matches!(self, Value::Null)
216    }
217}