use std::collections::HashMap;
use std::time::Duration;
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use crate::Value;
#[derive(Debug, Deserialize)]
pub struct Request {
pub id: u64,
pub query: String,
#[serde(default)]
pub graph: Option<String>,
}
#[derive(Debug, Serialize)]
pub struct Response {
pub id: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub rows: Option<Vec<HashMap<String, JsonValue>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
pub elapsed_ms: f64,
}
impl Response {
pub fn ok(id: u64, rows: Vec<HashMap<String, JsonValue>>, elapsed: Duration) -> Self {
Self {
id,
rows: Some(rows),
error: None,
elapsed_ms: elapsed.as_secs_f64() * 1000.0,
}
}
pub fn err(id: u64, msg: String, elapsed: Duration) -> Self {
Self {
id,
rows: None,
error: Some(msg),
elapsed_ms: elapsed.as_secs_f64() * 1000.0,
}
}
}
#[derive(Debug, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ClientMessage {
Auth { user: String, password: String },
Admin {
cmd: String,
#[serde(default)]
name: Option<String>,
},
}
#[derive(Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ServerMessage {
Hello {
version: &'static str,
auth_required: bool,
},
AuthOk { user: String },
AuthFail { error: String },
AdminOk {
#[serde(flatten)]
data: JsonValue,
},
AdminFail { error: String },
}
pub fn value_to_json(v: &Value) -> JsonValue {
match v {
Value::Null => JsonValue::Null,
Value::Bool(b) => JsonValue::Bool(*b),
Value::Int(i) => JsonValue::Number((*i).into()),
Value::Float(f) => {
if f.is_nan() || f.is_infinite() {
JsonValue::Null
} else {
serde_json::Number::from_f64(*f)
.map(JsonValue::Number)
.unwrap_or(JsonValue::Null)
}
}
Value::String(s) => JsonValue::String(s.clone()),
Value::List(items) => JsonValue::Array(items.iter().map(value_to_json).collect()),
Value::Map(m) => {
let obj: serde_json::Map<String, JsonValue> = m
.iter()
.map(|(k, v)| (k.clone(), value_to_json(v)))
.collect();
JsonValue::Object(obj)
}
}
}
pub fn row_to_json(row: &HashMap<String, Value>) -> HashMap<String, JsonValue> {
row.iter().map(|(k, v)| (k.clone(), value_to_json(v))).collect()
}