1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

use std::io::Cursor;
use std::io::Result;
use rowevents::value_type::*;
use byteorder::{LittleEndian, BigEndian, ReadBytesExt};
use rowevents::descriptor_datetime::*;
use rowevents::descriptor_decimal::*;


fn parse_string(metadata1: u8, metadata2: u8, data: &[u8]) -> Result<(ValueType, usize)> {
    let max_len = metadata1 + metadata2 * 256;  // 
    let strlen = data[0] as usize;
    let v = Vec::from(&data[1 .. strlen + 1]);
    Ok((ValueType::String(v), strlen + 1))
}

fn parse_varchar(metadata1: u8, metadata2: u8, data: &[u8]) -> Result<(ValueType, usize)> {
    let max_len: u32 = metadata1 as u32 + metadata2 as u32 * 256;   // Should ne LittleEndian
    let mut cursor = Cursor::new(&data);
    
    let (from, strlen) = if max_len < 256 {
        (1, cursor.read_u8()? as usize)
    } else {
        (2, cursor.read_i16::<LittleEndian>()? as usize)
    };

    let v = Vec::from(&data[from .. strlen + from]);
    Ok((ValueType::String(v), strlen + from))
}

fn parse_blob(metadata1: u8, metadata2: u8, data: &[u8]) -> Result<(ValueType, usize)> {
    let max_len = metadata1 + metadata2 * 256;
    let mut cursor = Cursor::new(&data);
    let strlen = cursor.read_i16::<LittleEndian>()? as usize;
    let v = Vec::from(&data[2 .. strlen + 2]);
    Ok((ValueType::String(v), strlen + 2)) 
}

pub fn parse_field(field_type: u8, nullable: bool, metadata1: u8, metadata2: u8, data: &[u8]) -> Result<(ValueType, usize)> {
    
    let (value, offset) = if field_type == FieldType::Tiny as u8 {
        let mut cursor = Cursor::new(&data);
        let v:i8 = cursor.read_i8()?;
        (ValueType::Tinyint(v), 1)
    } else if field_type == FieldType::Short as u8 {
        let mut cursor = Cursor::new(&data);
        let v:i16 = cursor.read_i16::<LittleEndian>()?;
        (ValueType::Shortint(v), 2)
    } else if field_type == FieldType::Long as u8 {
        let mut cursor = Cursor::new(&data);
        let v:i32 = cursor.read_i32::<LittleEndian>()?;
        (ValueType::Int(v), 4)
    } else if field_type == FieldType::Longlong as u8 {
        let mut cursor = Cursor::new(&data);
        let v:i64 = cursor.read_i64::<LittleEndian>()?;
        (ValueType::Longlong(v), 8)
    } else if field_type == FieldType::Float as u8 {
        let mut cursor = Cursor::new(&data);
        let v:f32 = cursor.read_f32::<LittleEndian>()?;
        (ValueType::Float(v), 4)
    } else if field_type == FieldType::Double as u8 {
        let mut cursor = Cursor::new(&data);
        let v:f64 = cursor.read_f64::<LittleEndian>()?;
        (ValueType::Double(v), 8)
    }  else if field_type == FieldType::Datetime2 as u8 {
        let (dt, offset) = parse_datetime2(metadata1, metadata2, data)?;
        (dt, offset)
    } else if field_type == FieldType::NewDecimal as u8 {
        let (dcm, offset) = parse_new_decimal(metadata1, metadata2, data)?;
        (dcm, offset)
    } else if field_type == FieldType::Varchar as u8 {
        let (strval, offset) = parse_varchar(metadata1, metadata2, data)?;
        (strval, offset)
    } else if field_type == FieldType::String as u8 {
        let (strval, offset) = parse_string(metadata1, metadata2, data)?;
        (strval, offset)
    } else if field_type == FieldType::Blob as u8 {
        let (strval, offset) = parse_blob(metadata1, metadata2, data)?;
        (strval, offset)
    } else if field_type == FieldType::Timestamp as u8 {
        let mut cursor = Cursor::new(&data);
        let v:u32 = cursor.read_u32::<BigEndian>()?;
        (ValueType::Timestamp(v), 4)
    } else if field_type == FieldType::Timestamp2 as u8 {
        let mut cursor = Cursor::new(&data);
        let v:u32 = cursor.read_u32::<BigEndian>()?;
        (ValueType::Timestamp(v), 4)
    } else {
        (ValueType::Unknown, 0)
    };
    Ok((value, offset))
}