Skip to main content

voltdb_client_rust/
encode.rs

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