1use std::{
7 borrow::{Borrow, Cow},
8 convert::TryFrom,
9 error::Error,
10 fmt,
11 ops::Deref,
12};
13
14use encoding_rs::WINDOWS_1252;
15use memchr::memchr;
16
17#[repr(transparent)]
18#[derive(Ord, PartialOrd, Eq, PartialEq)]
19pub struct Latin1String {
21 inner: Box<[u8]>,
22}
23
24impl Latin1String {
25 pub unsafe fn new(inner: Box<[u8]>) -> Self {
31 Self { inner }
32 }
33
34 pub fn encode(string: &str) -> Cow<Latin1Str> {
39 let (res, _enc, _has_replaced_chars) = WINDOWS_1252.encode(string);
40 match res {
41 Cow::Owned(o) => Cow::Owned(Self {
42 inner: o.into_boxed_slice(),
43 }),
44 Cow::Borrowed(b) => Cow::Borrowed(unsafe { Latin1Str::from_bytes_unchecked(b) }),
45 }
46 }
47}
48
49impl Borrow<Latin1Str> for Latin1String {
50 fn borrow(&self) -> &Latin1Str {
51 unsafe { Latin1Str::from_bytes_unchecked(&self.inner) }
52 }
53}
54
55impl Deref for Latin1String {
56 type Target = Latin1Str;
57
58 fn deref(&self) -> &Self::Target {
59 self.borrow()
60 }
61}
62
63impl From<Cow<'_, Latin1Str>> for Latin1String {
64 fn from(cow: Cow<'_, Latin1Str>) -> Self {
65 cow.into_owned()
66 }
67}
68
69impl From<&Latin1Str> for Latin1String {
70 fn from(src: &Latin1Str) -> Latin1String {
71 src.to_owned()
72 }
73}
74
75#[repr(transparent)]
76#[derive(PartialEq, PartialOrd, Eq, Ord)]
77pub struct Latin1Str {
79 #[allow(dead_code)]
80 inner: [u8],
81}
82
83#[cfg(feature = "serde-derives")]
84impl serde::Serialize for Latin1Str {
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: serde::Serializer,
88 {
89 serializer.serialize_str(self.decode().as_ref())
90 }
91}
92
93impl fmt::Debug for &'_ Latin1Str {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 self.decode().fmt(f)
96 }
97}
98
99impl ToOwned for Latin1Str {
100 type Owned = Latin1String;
101
102 fn to_owned(&self) -> Self::Owned {
103 Latin1String {
104 inner: self.as_bytes().into(),
105 }
106 }
107}
108
109impl Latin1Str {
110 pub(super) fn new(bytes: &[u8]) -> &Self {
112 let text = if let Some(index) = memchr(0x00, bytes) {
113 bytes.split_at(index).0
114 } else {
115 bytes
116 };
117 unsafe { Self::from_bytes_unchecked(text) }
118 }
119
120 pub unsafe fn from_bytes_unchecked(text: &[u8]) -> &Self {
126 &*(text as *const [u8] as *const Latin1Str)
127 }
128
129 pub fn as_bytes(&self) -> &[u8] {
131 &self.inner
132 }
133
134 pub fn len(&self) -> usize {
136 self.inner.len()
137 }
138
139 pub fn is_empty(&self) -> bool {
141 self.inner.is_empty()
142 }
143
144 pub fn req_buf_len(&self) -> usize {
147 self.inner.len() / 4 + 1
148 }
149
150 pub fn decode(&self) -> Cow<str> {
152 WINDOWS_1252.decode(self.as_bytes()).0
153 }
154}
155
156pub trait Context {
161 type String;
163 type I64;
165 type XML;
167}
168
169pub trait ValueMapperMut<TI, TO>
175where
176 TI: Context,
177 TO: Context,
178{
179 fn map_string(&mut self, from: &TI::String) -> TO::String;
181 fn map_i64(&mut self, from: &TI::I64) -> TO::I64;
183 fn map_xml(&mut self, from: &TI::XML) -> TO::XML;
185}
186
187#[derive(Debug, PartialEq)]
192#[cfg_attr(feature = "serde-derives", derive(serde::Serialize))]
193#[cfg_attr(feature = "serde-derives", serde(untagged))]
194pub enum Value<T: Context> {
195 Nothing,
197 Integer(i32),
199 Float(f32),
201 Text(T::String),
203 Boolean(bool),
205 BigInt(T::I64),
207 VarChar(T::XML),
209}
210
211impl<T: Context> Clone for Value<T>
212where
213 T::String: Clone,
214 T::XML: Clone,
215 T::I64: Clone,
216{
217 fn clone(&self) -> Self {
218 match self {
219 Value::Nothing => Value::Nothing,
220 Value::Integer(v) => Value::Integer(*v),
221 Value::Float(v) => Value::Float(*v),
222 Value::Text(v) => Value::Text(v.clone()),
223 Value::Boolean(v) => Value::Boolean(*v),
224 Value::BigInt(v) => Value::BigInt(v.clone()),
225 Value::VarChar(v) => Value::VarChar(v.clone()),
226 }
227 }
228}
229
230impl<T: Context> Copy for Value<T>
231where
232 T::String: Copy,
233 T::XML: Copy,
234 T::I64: Copy,
235{
236}
237
238impl<T: Context> Value<T> {
239 pub fn map<O, M>(&self, mapper: &mut M) -> Value<O>
241 where
242 O: Context,
243 M: ValueMapperMut<T, O>,
244 {
245 match self {
246 Value::Nothing => Value::Nothing,
247 Value::Integer(v) => Value::Integer(*v),
248 Value::Float(v) => Value::Float(*v),
249 Value::Text(v) => Value::Text(mapper.map_string(v)),
250 Value::Boolean(v) => Value::Boolean(*v),
251 Value::BigInt(v) => Value::BigInt(mapper.map_i64(v)),
252 Value::VarChar(v) => Value::VarChar(mapper.map_xml(v)),
253 }
254 }
255
256 pub fn into_opt_integer(self) -> Option<i32> {
258 if let Self::Integer(value) = self {
259 Some(value)
260 } else {
261 None
262 }
263 }
264
265 pub fn into_opt_float(self) -> Option<f32> {
267 if let Self::Float(value) = self {
268 Some(value)
269 } else {
270 None
271 }
272 }
273
274 pub fn into_opt_text(self) -> Option<T::String> {
276 if let Self::Text(value) = self {
277 Some(value)
278 } else {
279 None
280 }
281 }
282
283 pub fn into_opt_boolean(self) -> Option<bool> {
285 if let Self::Boolean(value) = self {
286 Some(value)
287 } else {
288 None
289 }
290 }
291
292 pub fn into_opt_big_int(self) -> Option<T::I64> {
294 if let Self::BigInt(value) = self {
295 Some(value)
296 } else {
297 None
298 }
299 }
300
301 pub fn into_opt_varchar(self) -> Option<T::XML> {
303 if let Self::VarChar(value) = self {
304 Some(value)
305 } else {
306 None
307 }
308 }
309}
310
311impl<T: Context> From<&Value<T>> for ValueType {
312 fn from(val: &Value<T>) -> Self {
313 match val {
314 Value::Nothing => ValueType::Nothing,
315 Value::Integer(_) => ValueType::Integer,
316 Value::Float(_) => ValueType::Float,
317 Value::Text(_) => ValueType::Text,
318 Value::Boolean(_) => ValueType::Boolean,
319 Value::BigInt(_) => ValueType::BigInt,
320 Value::VarChar(_) => ValueType::VarChar,
321 }
322 }
323}
324
325#[derive(Debug, Copy, Clone, PartialEq, Eq)]
327#[cfg_attr(feature = "serde-derives", derive(serde::Serialize))]
328pub enum ValueType {
329 Nothing,
331 Integer,
333 Float,
335 Text,
337 Boolean,
339 BigInt,
341 VarChar,
343}
344
345impl ValueType {
346 pub fn static_name(&self) -> &'static str {
348 match self {
349 ValueType::Nothing => "NULL",
350 ValueType::Integer => "INTEGER",
351 ValueType::Float => "FLOAT",
352 ValueType::Text => "TEXT",
353 ValueType::Boolean => "BOOLEAN",
354 ValueType::BigInt => "BIGINT",
355 ValueType::VarChar => "VARCHAR",
356 }
357 }
358}
359
360impl fmt::Display for ValueType {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 write!(f, "{}", self.static_name())
363 }
364}
365
366impl From<ValueType> for u8 {
367 fn from(value_type: ValueType) -> u8 {
368 match value_type {
369 ValueType::Nothing => 0,
370 ValueType::Integer => 1,
371 ValueType::Float => 3,
372 ValueType::Text => 4,
373 ValueType::Boolean => 5,
374 ValueType::BigInt => 6,
375 ValueType::VarChar => 8,
376 }
377 }
378}
379
380impl From<ValueType> for u32 {
381 fn from(value_type: ValueType) -> u32 {
382 u8::from(value_type).into()
383 }
384}
385
386#[derive(Debug, PartialEq, Eq)]
388pub struct UnknownValueType(u32);
389
390impl UnknownValueType {
391 pub fn value(&self) -> u32 {
393 self.0
394 }
395}
396
397impl Error for UnknownValueType {}
398impl fmt::Display for UnknownValueType {
399 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400 write!(f, "Unknown FDB value type {}", self.0)
401 }
402}
403
404impl TryFrom<u32> for ValueType {
405 type Error = UnknownValueType;
406
407 fn try_from(value_type: u32) -> Result<ValueType, Self::Error> {
408 match value_type {
409 0 => Ok(ValueType::Nothing),
410 1 => Ok(ValueType::Integer),
411 3 => Ok(ValueType::Float),
412 4 => Ok(ValueType::Text),
413 5 => Ok(ValueType::Boolean),
414 6 => Ok(ValueType::BigInt),
415 8 => Ok(ValueType::VarChar),
416 _ => Err(UnknownValueType(value_type)),
417 }
418 }
419}
420
421#[cfg(test)]
422mod tests {
423 use super::Latin1Str;
424
425 #[test]
426 fn test_latin1_req_bytes() {
427 assert_eq!(1, Latin1Str::new(b"a").req_buf_len());
428 assert_eq!(1, Latin1Str::new(b"ab").req_buf_len());
429 assert_eq!(1, Latin1Str::new(b"abc").req_buf_len());
430 assert_eq!(2, Latin1Str::new(b"abcd").req_buf_len());
431 assert_eq!(2, Latin1Str::new(b"abcde").req_buf_len());
432 assert_eq!(2, Latin1Str::new(b"abcdef").req_buf_len());
433 assert_eq!(2, Latin1Str::new(b"abcdefg").req_buf_len());
434 assert_eq!(3, Latin1Str::new(b"abcdefgh").req_buf_len());
435 }
436}