use serde::ser::{Serialize, SerializeMap, Serializer};
pub(crate) struct Line {
action: &'static str,
index: String,
id: Option<String>,
status: u16,
kind: LineKind,
}
enum LineKind {
Result(&'static str),
Queued { op_id: String },
Error(&'static str),
}
impl Line {
pub(crate) fn result(
action: &'static str,
index: String,
id: Option<String>,
status: u16,
outcome: &'static str,
) -> Self {
Self {
action,
index,
id,
status,
kind: LineKind::Result(outcome),
}
}
pub(crate) fn queued(
action: &'static str,
index: String,
id: Option<String>,
status: u16,
op_id: String,
) -> Self {
Self {
action,
index,
id,
status,
kind: LineKind::Queued { op_id },
}
}
pub(crate) fn error(
action: &'static str,
index: String,
id: Option<String>,
status: u16,
error: &'static str,
) -> Self {
Self {
action,
index,
id,
status,
kind: LineKind::Error(error),
}
}
pub(crate) fn is_error(&self) -> bool {
matches!(self.kind, LineKind::Error(_))
}
}
impl Serialize for Line {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut outer = serializer.serialize_map(Some(1))?;
outer.serialize_entry(self.action, &Body(self))?;
outer.end()
}
}
struct Body<'a>(&'a Line);
impl Serialize for Body<'_> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let line = self.0;
let mut m = serializer.serialize_map(None)?;
m.serialize_entry("_index", &line.index)?;
m.serialize_entry("_id", &line.id)?;
match &line.kind {
LineKind::Result(outcome) => {
m.serialize_entry("status", &line.status)?;
m.serialize_entry("result", outcome)?;
}
LineKind::Queued { op_id } => {
m.serialize_entry("op_id", op_id)?;
m.serialize_entry("status", &line.status)?;
m.serialize_entry("result", "queued")?;
}
LineKind::Error(error) => {
m.serialize_entry("status", &line.status)?;
m.serialize_entry("error", &ErrorType { r#type: error })?;
}
}
m.end()
}
}
#[derive(serde::Serialize)]
struct ErrorType {
r#type: &'static str,
}
#[derive(serde::Serialize)]
pub(crate) struct BulkBody<'a> {
pub(crate) took: u8,
pub(crate) errors: bool,
pub(crate) items: &'a [Option<Line>],
}