Skip to main content

voltdb_client_rust/
encode.rs

1use std::fmt::Debug;
2use std::str::Utf8Error;
3use std::sync::PoisonError;
4
5use bigdecimal::BigDecimal;
6use bigdecimal::num_bigint::BigInt;
7use bytebuffer::ByteBuffer;
8use chrono::{DateTime, Utc};
9use quick_error::quick_error;
10
11use crate::Column;
12use crate::chrono::TimeZone;
13use crate::response::VoltResponseInfo;
14
15#[allow(dead_code)]
16pub const ARRAY_COLUMN: i8 = -99;
17pub const NULL_COLUMN: i8 = 1;
18pub const TINYINT_COLUMN: i8 = 3;
19pub const SHORT_COLUMN: i8 = 4;
20pub const INT_COLUMN: i8 = 5;
21pub const LONG_COLUMN: i8 = 6;
22pub const FLOAT_COLUMN: i8 = 8;
23pub const STRING_COLUMN: i8 = 9;
24pub const TIMESTAMP_COLUMN: i8 = 11;
25pub const TABLE: i8 = 21;
26pub const DECIMAL_COLUMN: i8 = 22;
27pub const VAR_BIN_COLUMN: i8 = 25; // varbinary (int)(bytes)
28
29// Geospatial types (not supported - VoltDB types 26 and 27)
30#[allow(dead_code)]
31pub const GEOGRAPHY_POINT_COLUMN: i8 = 26;
32#[allow(dead_code)]
33pub const GEOGRAPHY_COLUMN: i8 = 27;
34
35pub const NULL_DECIMAL: [u8; 16] = [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
36
37pub const NULL_BIT_VALUE: [u8; 1] = [128];
38pub const NULL_SHORT_VALUE: [u8; 2] = [128, 0];
39pub const NULL_INT_VALUE: [u8; 4] = [128, 0, 0, 0];
40pub const NULL_LONG_VALUE: [u8; 8] = [128, 0, 0, 0, 0, 0, 0, 0];
41pub const NULL_TIMESTAMP: [u8; 8] = [128, 0, 0, 0, 0, 0, 0, 0];
42
43pub const NULL_FLOAT_VALUE: [u8; 8] = [255, 239, 255, 255, 255, 255, 255, 255];
44pub const NULL_VARCHAR: [u8; 4] = [255, 255, 255, 255];
45
46quick_error! {
47#[derive(Debug)]
48pub enum VoltError {
49        Io(err: std::io::Error) {
50            from()
51            display("I/O error: {}", err)
52            source(err)
53        }
54
55        RecvError(err: std::sync::mpsc::RecvError){
56            from()
57            display("Recv error: {}", err)
58            source(err)
59        }
60
61        ExecuteFail ( info: VoltResponseInfo ){
62            display("volt execute failed: {:?}", info)
63        }
64        InvalidColumnType(tp: i8) {
65            display("InvalidColumnType {}", tp)
66        }
67
68        MessageTooLarge(tp: usize) {
69            display("MessageTooLarge {}", tp)
70        }
71
72        NoValue (descr : String) {
73            display("Error {}", descr)
74        }
75        Other(descr: String) {
76            display("Error {}", descr)
77        }
78        NegativeNumTables (num: i16) {
79             display("Error {}", num)
80        }
81
82         Utf8Error(err : Utf8Error){
83            from()
84            display("Utf8 error: {}", err)
85            source(err)
86        }
87
88        PoisonError (descr: String){
89              display("Error {}", descr)
90        }
91        BadReturnStatusOnTable (status: i8) {
92             display("Error {}", status)
93        }
94        AuthFailed {
95             display("Auth failed")
96        }
97        ConnectionNotAvailable {
98             display("Connection lost")
99        }
100        InvalidConfig {
101             display("Invalid Config")
102        }
103        Timeout {
104             display("Operation timeout")
105        }
106        ConnectionClosed {
107             display("Connection Closed")
108        }
109        /// Returned when a non-Option type encounters a NULL value.
110        /// Use Option<T> if the column may contain NULL values.
111        UnexpectedNull(column: String) {
112            display("Unexpected NULL value in column '{}'. Use Option<T> for nullable columns.", column)
113        }
114}}
115
116impl<T> From<PoisonError<T>> for VoltError {
117    fn from(p: PoisonError<T>) -> VoltError {
118        VoltError::PoisonError(p.to_string().to_owned())
119    }
120}
121
122impl VoltError {
123    /// Returns true if this error indicates a fatal connection problem
124    /// that requires the connection to be replaced/healed.
125    pub fn is_connection_fatal(&self) -> bool {
126        match self {
127            // I/O errors that indicate connection problems
128            VoltError::Io(io_err) => matches!(
129                io_err.kind(),
130                std::io::ErrorKind::ConnectionReset
131                    | std::io::ErrorKind::ConnectionRefused
132                    | std::io::ErrorKind::ConnectionAborted
133                    | std::io::ErrorKind::BrokenPipe
134                    | std::io::ErrorKind::NotConnected
135                    | std::io::ErrorKind::UnexpectedEof
136            ),
137            // Explicit connection state errors
138            VoltError::ConnectionNotAvailable => true,
139            VoltError::ConnectionClosed => true,
140            // Timeout may indicate connection issues
141            VoltError::Timeout => true,
142            // RecvError typically means the background reader thread died
143            VoltError::RecvError(_) => true,
144            // Other errors are not connection-fatal
145            _ => false,
146        }
147    }
148}
149
150pub trait ValuePrimary {}
151
152//pub trait
153pub trait Value: Debug + Send + Sync {
154    fn get_write_length(&self) -> i32;
155    fn marshal(&self, bytebuffer: &mut ByteBuffer);
156    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8);
157    fn to_value_string(&self) -> String;
158    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError>
159    where
160        Self: Sized;
161}
162
163trait WriteBool {
164    fn write_bool(&mut self, val: bool);
165}
166
167impl WriteBool for ByteBuffer {
168    fn write_bool(&mut self, val: bool) {
169        if val {
170            self.write_i8(1)
171        } else {
172            self.write_i8(0);
173        }
174    }
175}
176
177impl Value for bool {
178    fn get_write_length(&self) -> i32 {
179        2
180    }
181
182    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
183        bytebuffer.write_i8(TINYINT_COLUMN);
184        bytebuffer.write_bool(*self);
185    }
186
187    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
188        bytebuffer.write_bool(*self);
189    }
190
191    fn to_value_string(&self) -> String {
192        self.to_string()
193    }
194
195    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
196        if bs[0] == 0 {
197            return Ok(false);
198        }
199        Ok(true)
200    }
201}
202
203impl Value for BigDecimal {
204    fn get_write_length(&self) -> i32 {
205        17
206    }
207
208    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
209        bytebuffer.write_i8(DECIMAL_COLUMN);
210        self.marshal_in_table(bytebuffer, DECIMAL_COLUMN);
211    }
212
213    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
214        let (b, _) = self.clone().with_scale(12).into_bigint_and_exponent();
215        let bs = b.to_signed_bytes_be();
216        let pad = 16 - bs.len();
217        if pad > 0 {
218            let arr = vec![0; pad];
219            bytebuffer.write_bytes(&arr)
220        }
221        bytebuffer.write_bytes(&bs);
222    }
223
224    fn to_value_string(&self) -> String {
225        self.to_string()
226    }
227
228    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError>
229    where
230        Self: Sized,
231    {
232        if bs == NULL_DECIMAL {
233            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
234        }
235        let int = BigInt::from_signed_bytes_be(&bs);
236        let decimal = BigDecimal::new(int, 12);
237        Ok(decimal)
238    }
239}
240
241impl Value for i8 {
242    fn get_write_length(&self) -> i32 {
243        2
244    }
245
246    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
247        bytebuffer.write_i8(TINYINT_COLUMN);
248        bytebuffer.write_i8(*self);
249    }
250
251    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
252        bytebuffer.write_i8(*self);
253    }
254
255    fn to_value_string(&self) -> String {
256        self.to_string()
257    }
258
259    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
260        if bs == NULL_BIT_VALUE {
261            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
262        }
263        let mut buffer = ByteBuffer::from_bytes(&bs);
264        let value = buffer.read_i8()?;
265        Ok(value)
266    }
267}
268
269impl Value for u8 {
270    fn get_write_length(&self) -> i32 {
271        2
272    }
273
274    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
275        bytebuffer.write_i8(TINYINT_COLUMN);
276        bytebuffer.write_u8(*self);
277    }
278
279    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
280        bytebuffer.write_u8(*self);
281    }
282
283    fn to_value_string(&self) -> String {
284        self.to_string()
285    }
286
287    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
288        if bs == NULL_BIT_VALUE {
289            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
290        }
291        let mut buffer = ByteBuffer::from_bytes(&bs);
292        let value = buffer.read_u8()?;
293        Ok(value)
294    }
295}
296
297impl Value for i16 {
298    fn get_write_length(&self) -> i32 {
299        3
300    }
301
302    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
303        bytebuffer.write_i8(SHORT_COLUMN);
304        bytebuffer.write_i16(*self);
305    }
306
307    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
308        bytebuffer.write_i16(*self);
309    }
310
311    fn to_value_string(&self) -> String {
312        self.to_string()
313    }
314
315    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
316        if bs == NULL_SHORT_VALUE {
317            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
318        }
319        let mut buffer = ByteBuffer::from_bytes(&bs);
320        let value = buffer.read_i16()?;
321        Ok(value)
322    }
323}
324
325impl Value for u16 {
326    fn get_write_length(&self) -> i32 {
327        3
328    }
329
330    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
331        bytebuffer.write_i8(SHORT_COLUMN);
332        bytebuffer.write_u16(*self);
333    }
334
335    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
336        bytebuffer.write_u16(*self);
337    }
338
339    fn to_value_string(&self) -> String {
340        self.to_string()
341    }
342
343    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
344        if bs == NULL_SHORT_VALUE {
345            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
346        }
347        let mut buffer = ByteBuffer::from_bytes(&bs);
348        let value = buffer.read_u16()?;
349        Ok(value)
350    }
351}
352
353impl Value for i32 {
354    fn get_write_length(&self) -> i32 {
355        5
356    }
357
358    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
359        bytebuffer.write_i8(INT_COLUMN);
360        bytebuffer.write_i32(*self);
361    }
362
363    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
364        bytebuffer.write_i32(*self);
365    }
366
367    fn to_value_string(&self) -> String {
368        self.to_string()
369    }
370
371    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
372        if bs == NULL_INT_VALUE {
373            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
374        }
375        let mut buffer = ByteBuffer::from_bytes(&bs);
376        let value = buffer.read_i32()?;
377        Ok(value)
378    }
379}
380
381impl Value for u32 {
382    fn get_write_length(&self) -> i32 {
383        5
384    }
385
386    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
387        bytebuffer.write_i8(INT_COLUMN);
388        bytebuffer.write_u32(*self);
389    }
390
391    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
392        bytebuffer.write_u32(*self);
393    }
394
395    fn to_value_string(&self) -> String {
396        self.to_string()
397    }
398
399    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
400        if bs == NULL_INT_VALUE {
401            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
402        }
403        let mut buffer = ByteBuffer::from_bytes(&bs);
404        let value = buffer.read_u32()?;
405        Ok(value)
406    }
407}
408
409impl Value for i64 {
410    fn get_write_length(&self) -> i32 {
411        9
412    }
413
414    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
415        bytebuffer.write_i8(LONG_COLUMN);
416        bytebuffer.write_i64(*self);
417    }
418
419    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
420        bytebuffer.write_i64(*self);
421    }
422
423    fn to_value_string(&self) -> String {
424        self.to_string()
425    }
426
427    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
428        if bs == NULL_LONG_VALUE {
429            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
430        }
431        let mut buffer = ByteBuffer::from_bytes(&bs);
432        let value = buffer.read_i64()?;
433        Ok(value)
434    }
435}
436
437impl Value for u64 {
438    fn get_write_length(&self) -> i32 {
439        9
440    }
441
442    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
443        bytebuffer.write_i8(LONG_COLUMN);
444        bytebuffer.write_u64(*self);
445    }
446
447    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
448        bytebuffer.write_u64(*self);
449    }
450
451    fn to_value_string(&self) -> String {
452        self.to_string()
453    }
454
455    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
456        if bs == NULL_LONG_VALUE {
457            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
458        }
459        let mut buffer = ByteBuffer::from_bytes(&bs);
460        let value = buffer.read_u64()?;
461        Ok(value)
462    }
463}
464
465impl Value for f64 {
466    fn get_write_length(&self) -> i32 {
467        9
468    }
469
470    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
471        bytebuffer.write_i8(FLOAT_COLUMN);
472        bytebuffer.write_f64(*self);
473    }
474
475    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
476        bytebuffer.write_f64(*self);
477    }
478
479    fn to_value_string(&self) -> String {
480        self.to_string()
481    }
482
483    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
484        if bs == NULL_FLOAT_VALUE {
485            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
486        }
487        let mut buffer = ByteBuffer::from_bytes(&bs);
488        let value = buffer.read_f64()?;
489        Ok(value)
490    }
491}
492
493impl Value for String {
494    fn get_write_length(&self) -> i32 {
495        (5 + self.len()) as i32
496    }
497
498    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
499        bytebuffer.write_i8(STRING_COLUMN);
500        bytebuffer.write_string(self);
501    }
502
503    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
504        bytebuffer.write_string(self);
505    }
506
507    fn to_value_string(&self) -> String {
508        self.to_string()
509    }
510
511    fn from_bytes(bs: Vec<u8>, table_column: &Column) -> Result<Self, VoltError> {
512        match table_column.header_type {
513            STRING_COLUMN => {
514                if bs == NULL_VARCHAR {
515                    return Err(VoltError::UnexpectedNull(table_column.header_name.clone()));
516                }
517                let mut buffer = ByteBuffer::from_bytes(&bs);
518                Ok(buffer.read_string()?)
519            }
520            _ => {
521                let res = crate::table::VoltTable::get_value_by_idx_column(table_column, bs)?;
522                match res {
523                    Some(v) => Ok(v.to_value_string()),
524                    None => Err(VoltError::UnexpectedNull(table_column.header_name.clone())),
525                }
526            }
527        }
528    }
529}
530
531impl Value for &str {
532    fn get_write_length(&self) -> i32 {
533        (5 + self.len()) as i32
534    }
535
536    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
537        bytebuffer.write_i8(STRING_COLUMN);
538        // write length , then data
539        bytebuffer.write_string(self);
540    }
541
542    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
543        bytebuffer.write_string(self);
544    }
545
546    fn to_value_string(&self) -> String {
547        self.to_string()
548    }
549
550    fn from_bytes(_bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
551        Err(VoltError::Other(
552            "&str::from_bytes is not supported. Use String::from_bytes instead.".to_string(),
553        ))
554    }
555}
556
557impl Value for Vec<u8> {
558    fn get_write_length(&self) -> i32 {
559        (5 + self.len()) as i32
560    }
561
562    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
563        bytebuffer.write_i8(VAR_BIN_COLUMN);
564        bytebuffer.write_u32(self.len() as u32);
565        bytebuffer.write_bytes(self);
566    }
567
568    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
569        bytebuffer.write_u32(self.len() as u32);
570        bytebuffer.write_bytes(self);
571    }
572
573    fn to_value_string(&self) -> String {
574        format!("{:?}", self)
575    }
576
577    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError> {
578        if bs == NULL_VARCHAR {
579            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
580        }
581        let mut bs = bs;
582        bs.drain(0..4);
583        Ok(bs)
584    }
585}
586
587impl Value for DateTime<Utc> {
588    fn get_write_length(&self) -> i32 {
589        9
590    }
591    fn marshal(&self, bytebuffer: &mut ByteBuffer) {
592        bytebuffer.write_i8(TIMESTAMP_COLUMN);
593        bytebuffer.write_i64(self.timestamp_millis() * 1000);
594    }
595
596    fn marshal_in_table(&self, bytebuffer: &mut ByteBuffer, _column_type: i8) {
597        bytebuffer.write_i64(self.timestamp_millis() * 1000);
598    }
599
600    fn to_value_string(&self) -> String {
601        self.to_string()
602    }
603
604    fn from_bytes(bs: Vec<u8>, _column: &Column) -> Result<Self, VoltError>
605    where
606        Self: Sized,
607    {
608        if bs == NULL_TIMESTAMP {
609            return Err(VoltError::UnexpectedNull(_column.header_name.clone()));
610        }
611        let mut buffer = ByteBuffer::from_bytes(&bs);
612        let time = buffer.read_i64()?;
613        let millis = time / 1000;
614        match Utc.timestamp_millis_opt(millis) {
615            chrono::LocalResult::Single(dt) => Ok(dt),
616            _ => Err(VoltError::Other(format!(
617                "Invalid timestamp value: {}",
618                millis
619            ))),
620        }
621    }
622}
623
624#[cfg(test)]
625mod tests {
626    use std::io;
627    use std::str::FromStr;
628
629    use bigdecimal::num_bigint::BigInt;
630    use chrono::TimeZone;
631
632    use crate::procedure_invocation::new_procedure_invocation;
633
634    use super::*;
635
636    #[test]
637    fn test_encoding_proc() {
638        let zero_vec: Vec<&dyn Value> = vec![&"select * from account limit 1;"];
639
640        let mut proc = new_procedure_invocation(1, false, &zero_vec, "@AdHoc");
641        let bs = proc.bytes();
642        assert_eq!(
643            bs,
644            vec!(
645                0, 0, 0, 56, 0, 0, 0, 0, 6, 64, 65, 100, 72, 111, 99, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
646                9, 0, 0, 0, 30, 115, 101, 108, 101, 99, 116, 32, 42, 32, 102, 114, 111, 109, 32,
647                97, 99, 99, 111, 117, 110, 116, 32, 108, 105, 109, 105, 116, 32, 49, 59
648            )
649        );
650    }
651
652    #[test]
653    fn test_time_stamp() {
654        let time = Utc.timestamp_millis_opt(1637323002445000 / 1000).unwrap();
655        println!("{}", time.timestamp_millis() * 1000);
656    }
657
658    #[test]
659    fn test_big_decimal() {
660        let bs: Vec<u8> = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 243, 16, 122, 64, 0];
661        let int = BigInt::from_signed_bytes_be(&bs);
662        let decimal = BigDecimal::new(int, 12);
663        let (b, _) = decimal.into_bigint_and_exponent();
664        let b = b.to_signed_bytes_be();
665        println!("{:?}", b);
666
667        let decimal = BigDecimal::from_str("1.11").unwrap().with_scale(12);
668        println!("{:?}", decimal.into_bigint_and_exponent());
669    }
670
671    #[test]
672    fn test_big_test_bytes() {
673        let i = ByteBuffer::from_bytes(&NULL_BIT_VALUE).read_i8().unwrap();
674        assert_eq!(i, -128);
675        let i = ByteBuffer::from_bytes(&NULL_SHORT_VALUE)
676            .read_i16()
677            .unwrap();
678        assert_eq!(i, -32768);
679        let i = ByteBuffer::from_bytes(&NULL_INT_VALUE).read_i32().unwrap();
680        assert_eq!(i, -2147483648);
681        let i = ByteBuffer::from_bytes(&NULL_LONG_VALUE).read_i64().unwrap();
682        assert_eq!(i, -9223372036854775808);
683
684        let column = Column {
685            header_name: "".to_string(),
686            header_type: STRING_COLUMN,
687        };
688
689        let vec = NULL_BIT_VALUE.to_vec();
690        let op: Option<i8> = Option::from_bytes(vec, &column).unwrap();
691        assert_eq!(None, op);
692        let vec = NULL_BIT_VALUE.to_vec();
693        let op: Option<u8> = Option::from_bytes(vec, &column).unwrap();
694        assert_eq!(None, op);
695        let vec = NULL_SHORT_VALUE.to_vec();
696        let op: Option<i16> = Option::from_bytes(vec, &column).unwrap();
697        assert_eq!(None, op);
698        let vec = NULL_SHORT_VALUE.to_vec();
699        let op: Option<u16> = Option::from_bytes(vec, &column).unwrap();
700        assert_eq!(None, op);
701        let vec = NULL_INT_VALUE.to_vec();
702        let op: Option<i32> = Option::from_bytes(vec, &column).unwrap();
703        assert_eq!(None, op);
704        let vec = NULL_INT_VALUE.to_vec();
705        let op: Option<u32> = Option::from_bytes(vec, &column).unwrap();
706        assert_eq!(None, op);
707
708        let vec = NULL_LONG_VALUE.to_vec();
709        let op: Option<i64> = Option::from_bytes(vec, &column).unwrap();
710        assert_eq!(None, op);
711        let vec = NULL_LONG_VALUE.to_vec();
712        let op: Option<u64> = Option::from_bytes(vec, &column).unwrap();
713        assert_eq!(None, op);
714
715        let vec = NULL_VARCHAR.to_vec();
716        let op: Option<String> = Option::from_bytes(vec, &column).unwrap();
717        assert_eq!(None, op);
718
719        let vec = NULL_VARCHAR.to_vec();
720        let op: Option<Vec<u8>> = Option::from_bytes(vec, &column).unwrap();
721        assert_eq!(None, op);
722
723        let vec = NULL_FLOAT_VALUE.to_vec();
724        let op: Option<f64> = Option::from_bytes(vec, &column).unwrap();
725        assert_eq!(None, op);
726
727        let vec = NULL_DECIMAL.to_vec();
728        let op: Option<BigDecimal> = Option::from_bytes(vec, &column).unwrap();
729        assert_eq!(None, op);
730
731        let vec = NULL_TIMESTAMP.to_vec();
732        let op: Option<DateTime<Utc>> = Option::from_bytes(vec, &column).unwrap();
733        assert_eq!(None, op);
734    }
735
736    #[test]
737    fn test_error() {
738        let err = VoltError::NoValue("key is af".to_owned());
739        println!("{:?} {} ", err, err);
740    }
741
742    #[test]
743    fn test_non_option_null_returns_error_i8() {
744        let column = Column {
745            header_name: "test_col".to_string(),
746            header_type: TINYINT_COLUMN,
747        };
748        let result = i8::from_bytes(NULL_BIT_VALUE.to_vec(), &column);
749        assert!(result.is_err());
750        match result {
751            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "test_col"),
752            _ => panic!("Expected UnexpectedNull error"),
753        }
754    }
755
756    #[test]
757    fn test_non_option_null_returns_error_i16() {
758        let column = Column {
759            header_name: "short_col".to_string(),
760            header_type: SHORT_COLUMN,
761        };
762        let result = i16::from_bytes(NULL_SHORT_VALUE.to_vec(), &column);
763        assert!(result.is_err());
764        match result {
765            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "short_col"),
766            _ => panic!("Expected UnexpectedNull error"),
767        }
768    }
769
770    #[test]
771    fn test_non_option_null_returns_error_i32() {
772        let column = Column {
773            header_name: "int_col".to_string(),
774            header_type: INT_COLUMN,
775        };
776        let result = i32::from_bytes(NULL_INT_VALUE.to_vec(), &column);
777        assert!(result.is_err());
778        match result {
779            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "int_col"),
780            _ => panic!("Expected UnexpectedNull error"),
781        }
782    }
783
784    #[test]
785    fn test_non_option_null_returns_error_i64() {
786        let column = Column {
787            header_name: "long_col".to_string(),
788            header_type: LONG_COLUMN,
789        };
790        let result = i64::from_bytes(NULL_LONG_VALUE.to_vec(), &column);
791        assert!(result.is_err());
792        match result {
793            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "long_col"),
794            _ => panic!("Expected UnexpectedNull error"),
795        }
796    }
797
798    #[test]
799    fn test_non_option_null_returns_error_f64() {
800        let column = Column {
801            header_name: "float_col".to_string(),
802            header_type: FLOAT_COLUMN,
803        };
804        let result = f64::from_bytes(NULL_FLOAT_VALUE.to_vec(), &column);
805        assert!(result.is_err());
806        match result {
807            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "float_col"),
808            _ => panic!("Expected UnexpectedNull error"),
809        }
810    }
811
812    #[test]
813    fn test_non_option_null_returns_error_string() {
814        let column = Column {
815            header_name: "str_col".to_string(),
816            header_type: STRING_COLUMN,
817        };
818        let result = String::from_bytes(NULL_VARCHAR.to_vec(), &column);
819        assert!(result.is_err());
820        match result {
821            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "str_col"),
822            _ => panic!("Expected UnexpectedNull error"),
823        }
824    }
825
826    #[test]
827    fn test_non_option_null_returns_error_vec_u8() {
828        let column = Column {
829            header_name: "bin_col".to_string(),
830            header_type: VAR_BIN_COLUMN,
831        };
832        let result = Vec::<u8>::from_bytes(NULL_VARCHAR.to_vec(), &column);
833        assert!(result.is_err());
834        match result {
835            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "bin_col"),
836            _ => panic!("Expected UnexpectedNull error"),
837        }
838    }
839
840    #[test]
841    fn test_non_option_null_returns_error_datetime() {
842        let column = Column {
843            header_name: "time_col".to_string(),
844            header_type: TIMESTAMP_COLUMN,
845        };
846        let result = DateTime::<Utc>::from_bytes(NULL_TIMESTAMP.to_vec(), &column);
847        assert!(result.is_err());
848        match result {
849            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "time_col"),
850            _ => panic!("Expected UnexpectedNull error"),
851        }
852    }
853
854    #[test]
855    fn test_non_option_null_returns_error_decimal() {
856        let column = Column {
857            header_name: "dec_col".to_string(),
858            header_type: DECIMAL_COLUMN,
859        };
860        let result = BigDecimal::from_bytes(NULL_DECIMAL.to_vec(), &column);
861        assert!(result.is_err());
862        match result {
863            Err(VoltError::UnexpectedNull(col)) => assert_eq!(col, "dec_col"),
864            _ => panic!("Expected UnexpectedNull error"),
865        }
866    }
867
868    #[test]
869    fn test_non_null_values_work() {
870        let column = Column {
871            header_name: "col".to_string(),
872            header_type: INT_COLUMN,
873        };
874        // Non-NULL value (42 as big-endian i32)
875        let result = i32::from_bytes(vec![0, 0, 0, 42], &column);
876        assert!(result.is_ok());
877        assert_eq!(result.unwrap(), 42);
878    }
879
880    #[test]
881    fn test_unexpected_null_error_message() {
882        let err = VoltError::UnexpectedNull("my_column".to_string());
883        let msg = format!("{}", err);
884        assert!(msg.contains("my_column"));
885        assert!(msg.contains("Option<T>"));
886    }
887
888    // Marshal tests for basic types
889    #[test]
890    fn test_i8_marshal() {
891        let val: i8 = 42;
892        let mut buf = ByteBuffer::new();
893        val.marshal(&mut buf);
894        let bytes = buf.into_vec();
895        assert_eq!(bytes[0] as i8, TINYINT_COLUMN);
896        assert_eq!(bytes[1], 42);
897    }
898
899    #[test]
900    fn test_i8_get_write_length() {
901        let val: i8 = 1;
902        assert_eq!(val.get_write_length(), 2);
903    }
904
905    #[test]
906    fn test_u8_marshal() {
907        let val: u8 = 255;
908        let mut buf = ByteBuffer::new();
909        val.marshal(&mut buf);
910        let bytes = buf.into_vec();
911        assert_eq!(bytes[0] as i8, TINYINT_COLUMN);
912        assert_eq!(bytes[1], 255);
913    }
914
915    #[test]
916    fn test_i16_marshal() {
917        let val: i16 = 1000;
918        let mut buf = ByteBuffer::new();
919        val.marshal(&mut buf);
920        let bytes = buf.into_vec();
921        assert_eq!(bytes[0] as i8, SHORT_COLUMN);
922        assert_eq!(val.get_write_length(), 3);
923    }
924
925    #[test]
926    fn test_u16_marshal() {
927        let val: u16 = 65535;
928        let mut buf = ByteBuffer::new();
929        val.marshal(&mut buf);
930        assert_eq!(buf.into_vec()[0] as i8, SHORT_COLUMN);
931    }
932
933    #[test]
934    fn test_i32_marshal() {
935        let val: i32 = 123456;
936        let mut buf = ByteBuffer::new();
937        val.marshal(&mut buf);
938        let bytes = buf.into_vec();
939        assert_eq!(bytes[0] as i8, INT_COLUMN);
940        assert_eq!(val.get_write_length(), 5);
941    }
942
943    #[test]
944    fn test_u32_marshal() {
945        let val: u32 = 4294967295;
946        let mut buf = ByteBuffer::new();
947        val.marshal(&mut buf);
948        assert_eq!(buf.into_vec()[0] as i8, INT_COLUMN);
949    }
950
951    #[test]
952    fn test_i64_marshal() {
953        let val: i64 = 9876543210;
954        let mut buf = ByteBuffer::new();
955        val.marshal(&mut buf);
956        let bytes = buf.into_vec();
957        assert_eq!(bytes[0] as i8, LONG_COLUMN);
958        assert_eq!(val.get_write_length(), 9);
959    }
960
961    #[test]
962    fn test_u64_marshal() {
963        let val: u64 = 18446744073709551615;
964        let mut buf = ByteBuffer::new();
965        val.marshal(&mut buf);
966        assert_eq!(buf.into_vec()[0] as i8, LONG_COLUMN);
967    }
968
969    #[test]
970    fn test_f64_marshal() {
971        #[allow(clippy::approx_constant)]
972        let val: f64 = 3.14159;
973        let mut buf = ByteBuffer::new();
974        val.marshal(&mut buf);
975        let bytes = buf.into_vec();
976        assert_eq!(bytes[0] as i8, FLOAT_COLUMN);
977        assert_eq!(val.get_write_length(), 9);
978    }
979
980    #[test]
981    fn test_bool_marshal_true() {
982        let val: bool = true;
983        let mut buf = ByteBuffer::new();
984        val.marshal(&mut buf);
985        let bytes = buf.into_vec();
986        assert_eq!(bytes[0] as i8, TINYINT_COLUMN);
987        assert_eq!(bytes[1], 1);
988    }
989
990    #[test]
991    fn test_bool_marshal_false() {
992        let val: bool = false;
993        let mut buf = ByteBuffer::new();
994        val.marshal(&mut buf);
995        let bytes = buf.into_vec();
996        assert_eq!(bytes[0] as i8, TINYINT_COLUMN);
997        assert_eq!(bytes[1], 0);
998    }
999
1000    #[test]
1001    fn test_string_marshal() {
1002        let val: String = "hello".to_string();
1003        let mut buf = ByteBuffer::new();
1004        val.marshal(&mut buf);
1005        let bytes = buf.into_vec();
1006        assert_eq!(bytes[0] as i8, STRING_COLUMN);
1007        assert_eq!(val.get_write_length(), 5 + 5); // header + "hello"
1008    }
1009
1010    #[test]
1011    fn test_str_marshal() {
1012        let val: &str = "world";
1013        let mut buf = ByteBuffer::new();
1014        val.marshal(&mut buf);
1015        let bytes = buf.into_vec();
1016        assert_eq!(bytes[0] as i8, STRING_COLUMN);
1017        assert_eq!(val.get_write_length(), 5 + 5); // header + "world"
1018    }
1019
1020    #[test]
1021    fn test_vec_u8_marshal() {
1022        let val: Vec<u8> = vec![1, 2, 3, 4, 5];
1023        let mut buf = ByteBuffer::new();
1024        val.marshal(&mut buf);
1025        let bytes = buf.into_vec();
1026        assert_eq!(bytes[0] as i8, VAR_BIN_COLUMN);
1027        assert_eq!(val.get_write_length(), 5 + 5); // header + 5 bytes
1028    }
1029
1030    #[test]
1031    fn test_datetime_marshal() {
1032        let val = Utc.timestamp_millis_opt(1000000).unwrap();
1033        let mut buf = ByteBuffer::new();
1034        val.marshal(&mut buf);
1035        let bytes = buf.into_vec();
1036        assert_eq!(bytes[0] as i8, TIMESTAMP_COLUMN);
1037        assert_eq!(val.get_write_length(), 9);
1038    }
1039
1040    #[test]
1041    fn test_bigdecimal_marshal() {
1042        let val = BigDecimal::from_str("123.456789").unwrap();
1043        let mut buf = ByteBuffer::new();
1044        val.marshal(&mut buf);
1045        let bytes = buf.into_vec();
1046        assert_eq!(bytes[0] as i8, DECIMAL_COLUMN);
1047        assert_eq!(val.get_write_length(), 17);
1048    }
1049
1050    // to_value_string tests
1051    #[test]
1052    fn test_i32_to_value_string() {
1053        let val: i32 = 42;
1054        assert_eq!(val.to_value_string(), "42");
1055    }
1056
1057    #[test]
1058    fn test_f64_to_value_string() {
1059        #[allow(clippy::approx_constant)]
1060        let val: f64 = 3.14;
1061        assert!(val.to_value_string().starts_with("3.14"));
1062    }
1063
1064    #[test]
1065    fn test_bool_to_value_string() {
1066        assert_eq!(true.to_value_string(), "true");
1067        assert_eq!(false.to_value_string(), "false");
1068    }
1069
1070    #[test]
1071    fn test_string_to_value_string() {
1072        let val = "hello".to_string();
1073        assert_eq!(val.to_value_string(), "hello");
1074    }
1075
1076    // Round-trip tests
1077    #[test]
1078    fn test_i32_roundtrip() {
1079        let col = Column {
1080            header_name: "test".to_string(),
1081            header_type: INT_COLUMN,
1082        };
1083        let original: i32 = 12345;
1084        let mut buf = ByteBuffer::new();
1085        original.marshal_in_table(&mut buf, INT_COLUMN);
1086        let bytes = buf.into_vec();
1087        let result = i32::from_bytes(bytes, &col).unwrap();
1088        assert_eq!(result, original);
1089    }
1090
1091    #[test]
1092    fn test_i64_roundtrip() {
1093        let col = Column {
1094            header_name: "test".to_string(),
1095            header_type: LONG_COLUMN,
1096        };
1097        let original: i64 = 9876543210;
1098        let mut buf = ByteBuffer::new();
1099        original.marshal_in_table(&mut buf, LONG_COLUMN);
1100        let bytes = buf.into_vec();
1101        let result = i64::from_bytes(bytes, &col).unwrap();
1102        assert_eq!(result, original);
1103    }
1104
1105    #[test]
1106    fn test_f64_roundtrip() {
1107        let col = Column {
1108            header_name: "test".to_string(),
1109            header_type: FLOAT_COLUMN,
1110        };
1111        #[allow(clippy::approx_constant)]
1112        let original: f64 = 3.14159;
1113        let mut buf = ByteBuffer::new();
1114        original.marshal_in_table(&mut buf, FLOAT_COLUMN);
1115        let bytes = buf.into_vec();
1116        let result = f64::from_bytes(bytes, &col).unwrap();
1117        assert!((result - original).abs() < 0.00001);
1118    }
1119
1120    // is_connection_fatal tests
1121    #[test]
1122    fn test_is_connection_fatal_io_connection_reset() {
1123        let err = VoltError::Io(io::Error::new(io::ErrorKind::ConnectionReset, "reset"));
1124        assert!(err.is_connection_fatal());
1125    }
1126
1127    #[test]
1128    fn test_is_connection_fatal_io_connection_refused() {
1129        let err = VoltError::Io(io::Error::new(io::ErrorKind::ConnectionRefused, "refused"));
1130        assert!(err.is_connection_fatal());
1131    }
1132
1133    #[test]
1134    fn test_is_connection_fatal_io_broken_pipe() {
1135        let err = VoltError::Io(io::Error::new(io::ErrorKind::BrokenPipe, "broken"));
1136        assert!(err.is_connection_fatal());
1137    }
1138
1139    #[test]
1140    fn test_is_connection_fatal_io_not_connected() {
1141        let err = VoltError::Io(io::Error::new(io::ErrorKind::NotConnected, "not connected"));
1142        assert!(err.is_connection_fatal());
1143    }
1144
1145    #[test]
1146    fn test_is_connection_fatal_io_unexpected_eof() {
1147        let err = VoltError::Io(io::Error::new(io::ErrorKind::UnexpectedEof, "eof"));
1148        assert!(err.is_connection_fatal());
1149    }
1150
1151    #[test]
1152    fn test_is_connection_fatal_io_other_not_fatal() {
1153        let err = VoltError::Io(io::Error::new(io::ErrorKind::InvalidData, "invalid"));
1154        assert!(!err.is_connection_fatal());
1155    }
1156
1157    #[test]
1158    fn test_is_connection_fatal_connection_not_available() {
1159        let err = VoltError::ConnectionNotAvailable;
1160        assert!(err.is_connection_fatal());
1161    }
1162
1163    #[test]
1164    fn test_is_connection_fatal_connection_closed() {
1165        let err = VoltError::ConnectionClosed;
1166        assert!(err.is_connection_fatal());
1167    }
1168
1169    #[test]
1170    fn test_is_connection_fatal_timeout() {
1171        let err = VoltError::Timeout;
1172        assert!(err.is_connection_fatal());
1173    }
1174
1175    #[test]
1176    fn test_is_connection_fatal_no_value_not_fatal() {
1177        let err = VoltError::NoValue("test".to_string());
1178        assert!(!err.is_connection_fatal());
1179    }
1180
1181    #[test]
1182    fn test_is_connection_fatal_auth_failed_not_fatal() {
1183        let err = VoltError::AuthFailed;
1184        assert!(!err.is_connection_fatal());
1185    }
1186
1187    #[test]
1188    fn test_is_connection_fatal_unexpected_null_not_fatal() {
1189        let err = VoltError::UnexpectedNull("col".to_string());
1190        assert!(!err.is_connection_fatal());
1191    }
1192}