use d_engine_core::client::ErrorCode;
use d_engine_core::client::KvEntry;
use d_engine_proto::client::ClientResponse;
use d_engine_proto::client::client_response::SuccessResult;
use tracing::error;
use crate::ClientApiError;
pub trait ClientResponseExt {
#[allow(dead_code)]
fn into_write_result(self) -> std::result::Result<bool, ClientApiError>;
fn into_read_results(self) -> std::result::Result<Vec<Option<KvEntry>>, ClientApiError>;
fn validate_error(&self) -> std::result::Result<(), ClientApiError>;
#[allow(dead_code)]
fn is_write_success(&self) -> bool;
}
impl ClientResponseExt for ClientResponse {
fn into_write_result(self) -> std::result::Result<bool, ClientApiError> {
self.validate_error()?;
match self.success_result {
Some(SuccessResult::WriteResult(result)) => Ok(result.succeeded),
other => {
let found = match &other {
Some(SuccessResult::ReadData(_)) => "ReadData",
Some(_) => "Unknown",
None => "None",
};
error!(
"Unexpected response type for write operation: expected WriteResult, found {found}"
);
Err(ClientApiError::Protocol {
code: ErrorCode::InvalidResponse,
message: format!(
"Unexpected response type: expected WriteResult, found {found}"
),
supported_versions: None,
})
}
}
}
fn into_read_results(self) -> std::result::Result<Vec<Option<KvEntry>>, ClientApiError> {
self.validate_error()?;
match &self.success_result {
Some(SuccessResult::ReadData(data)) => data
.results
.clone()
.into_iter()
.map(|item| {
Ok(Some(KvEntry {
key: item.key,
value: item.value,
}))
})
.collect(),
_ => {
let found = match &self.success_result {
Some(SuccessResult::WriteResult(_)) => "WriteResult",
None => "None",
_ => "Unknown",
};
error!(
"Unexpected response type for read operation: expected ReadData, found {}",
found
);
Err(ClientApiError::Protocol {
code: ErrorCode::InvalidResponse,
message: format!("Unexpected response type: expected ReadData, found {found}",),
supported_versions: None,
})
}
}
}
fn validate_error(&self) -> std::result::Result<(), ClientApiError> {
match ErrorCode::try_from(self.error).unwrap_or(ErrorCode::Uncategorized) {
ErrorCode::Success => Ok(()),
e => Err(e.into()),
}
}
fn is_write_success(&self) -> bool {
self.error == ErrorCode::Success as i32
&& matches!(&self.success_result, Some(SuccessResult::WriteResult(w)) if w.succeeded)
}
}