use std::ffi::c_char;
use std::slice;
use crate::bindings;
#[non_exhaustive]
#[derive(Clone, Copy, Debug)]
pub enum Value<'a> {
Decimal(&'a [u8]),
I8(i8),
I16(i16),
Long(i64),
LongLong(i64),
F32(f32),
F64(f64),
Null,
Time, TimeStamp, Date, DateTime, Year, String(&'a [u8]),
Blob(&'a [u8]),
Json(&'a [u8]),
}
impl<'a> Value<'a> {
pub(crate) unsafe fn from_str_ptr(
ty: bindings::enum_field_types::Type,
ptr: *const c_char,
len: usize,
) -> Self {
let bytes: &[u8] = unsafe { slice::from_raw_parts(ptr.cast(), len) };
let tostr = |bytes| std::str::from_utf8(bytes).unwrap();
match ty {
bindings::enum_field_types::MYSQL_TYPE_DECIMAL => Self::Decimal(bytes),
bindings::enum_field_types::MYSQL_TYPE_TINY => Self::I8(tostr(bytes).parse().unwrap()),
bindings::enum_field_types::MYSQL_TYPE_SHORT => {
Self::I16(tostr(bytes).parse().unwrap())
}
bindings::enum_field_types::MYSQL_TYPE_LONG => {
Self::Long(tostr(bytes).parse().unwrap())
}
bindings::enum_field_types::MYSQL_TYPE_LONGLONG => {
Self::LongLong(tostr(bytes).parse().unwrap())
}
bindings::enum_field_types::MYSQL_TYPE_FLOAT => {
Self::F32(tostr(bytes).parse().unwrap())
}
bindings::enum_field_types::MYSQL_TYPE_DOUBLE => {
Self::F64(tostr(bytes).parse().unwrap())
}
bindings::enum_field_types::MYSQL_TYPE_NULL => Self::Null,
bindings::enum_field_types::MYSQL_TYPE_TIMESTAMP => todo!(),
bindings::enum_field_types::MYSQL_TYPE_INT24 => todo!(),
bindings::enum_field_types::MYSQL_TYPE_DATE => todo!(),
bindings::enum_field_types::MYSQL_TYPE_TIME => todo!(),
bindings::enum_field_types::MYSQL_TYPE_DATETIME => todo!(),
bindings::enum_field_types::MYSQL_TYPE_YEAR => todo!(),
bindings::enum_field_types::MYSQL_TYPE_NEWDATE => todo!(),
bindings::enum_field_types::MYSQL_TYPE_VARCHAR => todo!(),
bindings::enum_field_types::MYSQL_TYPE_BIT => todo!(),
bindings::enum_field_types::MYSQL_TYPE_TIMESTAMP2 => todo!(),
bindings::enum_field_types::MYSQL_TYPE_DATETIME2 => todo!(),
bindings::enum_field_types::MYSQL_TYPE_TIME2 => todo!(),
bindings::enum_field_types::MYSQL_TYPE_BLOB_COMPRESSED => todo!(),
bindings::enum_field_types::MYSQL_TYPE_VARCHAR_COMPRESSED => todo!(),
bindings::enum_field_types::MYSQL_TYPE_NEWDECIMAL => todo!(),
bindings::enum_field_types::MYSQL_TYPE_ENUM => todo!(),
bindings::enum_field_types::MYSQL_TYPE_SET => todo!(),
bindings::enum_field_types::MYSQL_TYPE_TINY_BLOB
| bindings::enum_field_types::MYSQL_TYPE_MEDIUM_BLOB
| bindings::enum_field_types::MYSQL_TYPE_LONG_BLOB
| bindings::enum_field_types::MYSQL_TYPE_BLOB => Self::Blob(bytes),
bindings::enum_field_types::MYSQL_TYPE_VAR_STRING
| bindings::enum_field_types::MYSQL_TYPE_STRING => Self::String(bytes),
bindings::enum_field_types::MYSQL_TYPE_GEOMETRY => todo!(),
_ => todo!(),
}
}
pub fn as_int(&self) -> Option<i64> {
match self {
Value::I8(v) => Some((*v).into()),
Value::I16(v) => Some((*v).into()),
Value::Long(v) | Value::LongLong(v) => Some((*v).into()),
_ => None,
}
}
pub fn as_str(&self) -> Option<&'a str> {
match self {
Value::String(v) => std::str::from_utf8(v).ok(),
_ => None,
}
}
pub fn as_bytes(&self) -> Option<&'a [u8]> {
match self {
Value::String(v) | Value::Blob(v) | Value::Json(v) => Some(*v),
_ => None,
}
}
}