use std::str::from_utf8;
use serde_json::Value as JsonValue;
#[derive(Clone, PartialEq, PartialOrd, Debug)]
pub enum Value {
Null,
Bytes(Vec<u8>),
Int(i64),
UInt(u64),
Float(f32),
Double(f64),
Date(u16, u8, u8, u8, u8, u8, u32),
Time(bool, u32, u8, u8, u8, u32),
}
macro_rules! into_value_impl (
(signed $t:ty) => (
impl From<$t> for Value {
fn from(x: $t) -> Value {
Value::Int(x as i64)
}
}
);
(unsigned $t:ty) => (
impl From<$t> for Value {
fn from(x: $t) -> Value {
Value::UInt(x as u64)
}
}
);
);
into_value_impl!(signed i8);
into_value_impl!(signed i16);
into_value_impl!(signed i32);
into_value_impl!(signed i64);
into_value_impl!(signed isize);
into_value_impl!(unsigned u8);
into_value_impl!(unsigned u16);
into_value_impl!(unsigned u32);
into_value_impl!(unsigned u64);
into_value_impl!(unsigned usize);
impl From<f32> for Value {
fn from(x: f32) -> Value {
Value::Float(x)
}
}
impl From<f64> for Value {
fn from(x: f64) -> Value {
Value::Double(x)
}
}
impl From<bool> for Value {
fn from(x: bool) -> Value {
Value::Int(if x { 1 } else { 0 })
}
}
impl<'a> From<&'a [u8]> for Value {
fn from(x: &'a [u8]) -> Value {
Value::Bytes(x.into())
}
}
impl From<Vec<u8>> for Value {
fn from(x: Vec<u8>) -> Value {
Value::Bytes(x)
}
}
impl<'a> From<&'a str> for Value {
fn from(x: &'a str) -> Value {
let string: String = x.into();
Value::Bytes(string.into_bytes())
}
}
impl From<String> for Value {
fn from(x: String) -> Value {
Value::Bytes(x.into_bytes())
}
}
macro_rules! from_array_impl {
($n:expr) => {
impl From<[u8; $n]> for Value {
fn from(x: [u8; $n]) -> Value {
Value::from(&x[..])
}
}
};
}
from_array_impl!(0);
from_array_impl!(1);
from_array_impl!(2);
from_array_impl!(3);
from_array_impl!(4);
from_array_impl!(5);
from_array_impl!(6);
from_array_impl!(7);
from_array_impl!(8);
from_array_impl!(9);
from_array_impl!(10);
from_array_impl!(11);
from_array_impl!(12);
from_array_impl!(13);
from_array_impl!(14);
from_array_impl!(15);
from_array_impl!(16);
from_array_impl!(17);
from_array_impl!(18);
from_array_impl!(19);
from_array_impl!(20);
from_array_impl!(21);
from_array_impl!(22);
from_array_impl!(23);
from_array_impl!(24);
from_array_impl!(25);
from_array_impl!(26);
from_array_impl!(27);
from_array_impl!(28);
from_array_impl!(29);
from_array_impl!(30);
from_array_impl!(31);
from_array_impl!(32);
pub fn escape_string(string: &str) -> String {
string
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("'", "\\'")
.replace("\0", "\\0")
.replace("\x08", "\\b")
.replace("\x09", "\\t")
.replace("\x1a", "\\z")
.replace("\n", "\\n")
.replace("\r", "\\r")
}
pub fn json_value_to_sea_value(v: &JsonValue) -> Value {
match v {
JsonValue::Null => Value::Null,
JsonValue::Bool(v) => Value::Int(v.to_owned().into()),
JsonValue::Number(v) =>
if v.is_f64() {
Value::Double(v.as_f64().unwrap())
} else if v.is_i64() {
Value::Int(v.as_i64().unwrap())
} else if v.is_u64() {
Value::UInt(v.as_u64().unwrap())
} else {
unimplemented!()
},
JsonValue::String(v) => Value::Bytes(v.as_bytes().to_vec()),
JsonValue::Array(_) => unimplemented!(),
JsonValue::Object(_) => unimplemented!(),
}
}
#[allow(clippy::many_single_char_names)]
pub fn sea_value_to_json_value(v: &Value) -> JsonValue {
match v {
Value::Null => JsonValue::Null,
Value::Bytes(v) => JsonValue::String(from_utf8(v).unwrap().to_string()),
Value::Int(v) => (*v).into(),
Value::UInt(v) => (*v).into(),
Value::Float(v) => (*v).into(),
Value::Double(v) => (*v).into(),
Value::Date(y, m, d, 0, 0, 0, 0) => {
JsonValue::String(format!("'{:04}-{:02}-{:02}'", y, m, d))
},
Value::Date(y, m, d, h, i, s, 0) => {
JsonValue::String(format!("'{:04}-{:02}-{:02} {:02}:{:02}:{:02}'", y, m, d, h, i, s))
},
Value::Date(y, m, d, h, i, s, u) => {
JsonValue::String(format!(
"'{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:06}'",
y, m, d, h, i, s, u
))
},
Value::Time(neg, d, h, i, s, 0) => {
if *neg {
JsonValue::String(format!("'-{:03}:{:02}:{:02}'", d * 24 + u32::from(*h), i, s))
} else {
JsonValue::String(format!("'{:03}:{:02}:{:02}'", d * 24 + u32::from(*h), i, s))
}
},
Value::Time(neg, d, h, i, s, u) => {
if *neg {
JsonValue::String(format!("'-{:03}:{:02}:{:02}.{:06}'", d * 24 + u32::from(*h), i, s, u))
} else {
JsonValue::String(format!("'{:03}:{:02}:{:02}.{:06}'", d * 24 + u32::from(*h), i, s, u))
}
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_escape_1() {
assert_eq!(escape_string(r#" "abc" "#), r#" \"abc\" "#.to_owned());
}
#[test]
fn test_escape_2() {
assert_eq!(escape_string("a\nb\tc"), "a\\nb\\tc".to_owned());
}
#[test]
fn test_escape_3() {
assert_eq!(escape_string("a\\b"), "a\\\\b".to_owned());
}
}