use serde_json;
use serde_json::value::RawValue;
use std::fmt;
#[repr(C)]
#[derive(Clone, Copy, PartialEq)]
pub enum JsonType {
String,
Number,
Boolean,
Null,
Object,
Array,
}
impl From<&serde_json::Value> for JsonType {
fn from(value: &serde_json::Value) -> Self {
match value {
serde_json::Value::String(_) => Self::String,
serde_json::Value::Number(_) => Self::Number,
serde_json::Value::Bool(_) => Self::Boolean,
serde_json::Value::Null => Self::Null,
serde_json::Value::Object(_) => Self::Object,
serde_json::Value::Array(_) => Self::Array,
}
}
}
impl fmt::Display for JsonType {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::String => write!(formatter, "String"),
Self::Number => write!(formatter, "Number"),
Self::Boolean => write!(formatter, "Boolean"),
Self::Null => write!(formatter, "Null"),
Self::Object => write!(formatter, "Object"),
Self::Array => write!(formatter, "Array"),
}
}
}
#[derive(Clone)]
pub struct CommandMessage {
pub json: Vec<u8>,
pub key: Vec<u8>,
pub value: Vec<u8>,
pub value_type: JsonType,
pub error: Option<String>, }
impl CommandMessage {
pub fn parse(json: &[u8]) -> Option<Self> {
let map: std::collections::HashMap<String, &RawValue> = serde_json::from_slice(json).ok()?;
if map.len() != 1 {
return None;
}
let (key, raw_value) = map.iter().next()?;
let value = serde_json::from_str::<serde_json::Value>(raw_value.get()).ok()?;
Some(Self {
json: json.to_vec(),
key: key.as_bytes().to_vec(),
value: raw_value.get().as_bytes().to_vec(),
value_type: (&value).into(),
error: value.as_object().and_then(|o| o.get("error")).and_then(|v| v.as_str()).map(String::from),
})
}
}