sqlite_ll/value.rs
1use core::ffi::c_int;
2use core::fmt;
3
4use alloc::string::String;
5use alloc::vec::Vec;
6
7use sqlite3_sys as ffi;
8
9/// The type of a value.
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11#[non_exhaustive]
12pub struct Type(c_int);
13
14impl Type {
15 /// Construct from a raw type.
16 #[inline]
17 pub(crate) fn from_raw(raw: c_int) -> Self {
18 Self(raw)
19 }
20
21 /// The blob type.
22 pub const BLOB: Self = Self(ffi::SQLITE_BLOB);
23 /// The text type.
24 pub const TEXT: Self = Self(ffi::SQLITE_TEXT);
25 /// The floating-point type.
26 pub const FLOAT: Self = Self(ffi::SQLITE_FLOAT);
27 /// The integer type.
28 pub const INTEGER: Self = Self(ffi::SQLITE_INTEGER);
29 /// The null type.
30 pub const NULL: Self = Self(ffi::SQLITE_NULL);
31}
32
33impl fmt::Display for Type {
34 #[inline]
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self.0 {
37 ffi::SQLITE_BLOB => write!(f, "BLOB"),
38 ffi::SQLITE_TEXT => write!(f, "TEXT"),
39 ffi::SQLITE_FLOAT => write!(f, "FLOAT"),
40 ffi::SQLITE_INTEGER => write!(f, "INTEGER"),
41 ffi::SQLITE_NULL => write!(f, "NULL"),
42 _ => write!(f, "UNKNOWN"),
43 }
44 }
45}
46
47#[derive(Clone, Debug, PartialEq)]
48pub(crate) enum Kind {
49 Null,
50 Blob(Vec<u8>),
51 Text(String),
52 Float(f64),
53 Integer(i64),
54}
55
56/// A dynamic value.
57#[derive(Clone, PartialEq)]
58pub struct Value {
59 pub(super) kind: Kind,
60}
61
62impl Value {
63 /// Construct a null value.
64 ///
65 /// # Examples
66 ///
67 /// ```
68 /// use sqlite_ll::Value;
69 ///
70 /// let value = Value::null();
71 /// assert!(value.is_null());
72 /// ```
73 #[inline]
74 pub const fn null() -> Self {
75 Self { kind: Kind::Null }
76 }
77
78 /// Construct a blob value.
79 ///
80 /// # Examples
81 ///
82 /// ```
83 /// use sqlite_ll::Value;
84 ///
85 /// let value = Value::blob(Vec::new());
86 /// assert_eq!(value.as_blob(), Some(&[][..]));
87 /// ```
88 #[inline]
89 pub const fn blob(value: Vec<u8>) -> Self {
90 Self {
91 kind: Kind::Blob(value),
92 }
93 }
94
95 /// Construct a text value.
96 ///
97 /// # Examples
98 ///
99 /// ```
100 /// use sqlite_ll::Value;
101 ///
102 /// let value = Value::text(String::new());
103 /// assert_eq!(value.as_text(), Some(""));
104 ///
105 /// let value = Value::text(String::from("hello"));
106 /// assert_eq!(value.as_text(), Some("hello"));
107 /// ```
108 #[inline]
109 pub const fn text(value: String) -> Self {
110 Self {
111 kind: Kind::Text(value),
112 }
113 }
114
115 /// Construct a float value.
116 ///
117 /// # Examples
118 ///
119 /// ```
120 /// use sqlite_ll::Value;
121 ///
122 /// let value = Value::float(42.0);
123 /// assert_eq!(value.as_float(), Some(42.0));
124 /// ```
125 #[inline]
126 pub const fn float(value: f64) -> Self {
127 Self {
128 kind: Kind::Float(value),
129 }
130 }
131
132 /// Construct a integer value.
133 ///
134 /// # Examples
135 ///
136 /// ```
137 /// use sqlite_ll::Value;
138 ///
139 /// let value = Value::integer(42);
140 /// assert_eq!(value.as_integer(), Some(42));
141 /// ```
142 #[inline]
143 pub const fn integer(value: i64) -> Self {
144 Self {
145 kind: Kind::Integer(value),
146 }
147 }
148
149 /// Return whether the value is `Null`.
150 ///
151 /// # Examples
152 ///
153 /// ```
154 /// use sqlite_ll::Value;
155 ///
156 /// let value = Value::null();
157 /// assert!(value.is_null());
158 /// ```
159 #[inline]
160 pub const fn is_null(&self) -> bool {
161 matches!(self.kind, Kind::Null)
162 }
163
164 /// Return the binary data if the value is `Binary`.
165 ///
166 /// # Examples
167 ///
168 /// ```
169 /// use sqlite_ll::Value;
170 ///
171 /// let value = Value::blob(Vec::new());
172 /// assert_eq!(value.as_blob(), Some(&[][..]));
173 /// ```
174 #[inline]
175 pub const fn as_blob(&self) -> Option<&[u8]> {
176 if let Kind::Blob(value) = &self.kind {
177 return Some(value.as_slice());
178 }
179
180 None
181 }
182
183 /// Return the string if the value is `String`.
184 ///
185 /// # Examples
186 ///
187 /// ```
188 /// use sqlite_ll::Value;
189 ///
190 /// let value = Value::text(String::new());
191 /// assert_eq!(value.as_text(), Some(""));
192 ///
193 /// let value = Value::text(String::from("hello"));
194 /// assert_eq!(value.as_text(), Some("hello"));
195 /// ```
196 #[inline]
197 pub const fn as_text(&self) -> Option<&str> {
198 if let Kind::Text(value) = &self.kind {
199 return Some(value.as_str());
200 }
201
202 None
203 }
204
205 /// Return the floating-point number if the value is `Float`.
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// use sqlite_ll::Value;
211 ///
212 /// let value = Value::float(42.0);
213 /// assert_eq!(value.as_float(), Some(42.0));
214 /// ```
215 #[inline]
216 pub const fn as_float(&self) -> Option<f64> {
217 if let Kind::Float(value) = self.kind {
218 return Some(value);
219 }
220
221 None
222 }
223
224 /// Return the integer number if the value is `Integer`.
225 ///
226 /// # Examples
227 ///
228 /// ```
229 /// use sqlite_ll::Value;
230 ///
231 /// let value = Value::integer(42);
232 /// assert_eq!(value.as_integer(), Some(42));
233 /// ```
234 #[inline]
235 pub const fn as_integer(&self) -> Option<i64> {
236 if let Kind::Integer(value) = self.kind {
237 return Some(value);
238 }
239
240 None
241 }
242
243 /// Return the type.
244 #[inline]
245 pub const fn kind(&self) -> Type {
246 match &self.kind {
247 Kind::Blob(_) => Type::BLOB,
248 Kind::Float(_) => Type::FLOAT,
249 Kind::Integer(_) => Type::INTEGER,
250 Kind::Text(_) => Type::TEXT,
251 Kind::Null => Type::NULL,
252 }
253 }
254}
255
256impl fmt::Debug for Value {
257 #[inline]
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 self.kind.fmt(f)
260 }
261}