use serde::{Deserialize, Serialize};
use crate::error::CoolError;
#[cfg(test)]
mod tests;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BatchItemResult<T> {
pub index: usize,
#[serde(flatten)]
pub status: BatchItemStatus<T>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "status", rename_all = "lowercase")]
pub enum BatchItemStatus<T> {
Ok { value: T },
Error { error: BatchItemError },
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BatchItemError {
pub code: String,
pub message: String,
}
impl BatchItemError {
pub fn from_cool(error: &CoolError) -> Self {
Self {
code: error.code().to_owned(),
message: error.public_message().into_owned(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct BatchSummary {
pub total: usize,
pub ok: usize,
pub err: usize,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BatchResponse<T> {
pub results: Vec<BatchItemResult<T>>,
pub summary: BatchSummary,
}
impl<T> BatchResponse<T> {
pub fn from_results(per_item: Vec<Result<T, CoolError>>) -> Self {
let total = per_item.len();
let mut ok = 0usize;
let mut err = 0usize;
let results = per_item
.into_iter()
.enumerate()
.map(|(index, outcome)| match outcome {
Ok(value) => {
ok += 1;
BatchItemResult {
index,
status: BatchItemStatus::Ok { value },
}
}
Err(error) => {
err += 1;
BatchItemResult {
index,
status: BatchItemStatus::Error {
error: BatchItemError::from_cool(&error),
},
}
}
})
.collect();
Self {
results,
summary: BatchSummary { total, ok, err },
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BatchRequest<I> {
pub items: Vec<I>,
}
pub const BATCH_MAX_ITEMS: usize = 1000;
pub fn find_duplicate_position<K: Eq + std::hash::Hash>(
keys: impl IntoIterator<Item = K>,
) -> Option<(usize, usize)> {
let mut seen: std::collections::HashMap<K, usize> = std::collections::HashMap::new();
for (index, key) in keys.into_iter().enumerate() {
if let Some(&first) = seen.get(&key) {
return Some((first, index));
}
seen.insert(key, index);
}
None
}