use serde::{Deserialize, Serialize, Serializer};
use std::borrow::Cow;
use thiserror::Error;
use warg_crypto::hash::HashAlgorithm;
use warg_protocol::registry::RegistryIndex;
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LedgerSourcesResponse {
pub hash_algorithm: HashAlgorithm,
pub sources: Vec<LedgerSource>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LedgerSource {
pub first_registry_index: RegistryIndex,
pub last_registry_index: RegistryIndex,
pub url: String,
pub content_type: LedgerSourceContentType,
#[serde(default, skip_serializing_if = "is_false")]
pub accept_ranges: bool,
}
fn is_false(b: &bool) -> bool {
!b
}
#[derive(Default, PartialEq, Serialize, Deserialize, Debug)]
pub enum LedgerSourceContentType {
#[default]
#[serde(rename = "application/vnd.warg.ledger.packed")]
Packed,
}
impl LedgerSourceContentType {
pub fn as_str(&self) -> &'static str {
match self {
Self::Packed => "application/vnd.warg.ledger.packed",
}
}
}
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum LedgerError {
#[error("{message}")]
Message {
status: u16,
message: String,
},
}
impl LedgerError {
pub fn status(&self) -> u16 {
match self {
Self::Message { status, .. } => *status,
}
}
}
#[derive(Serialize, Deserialize)]
#[serde(untagged, rename_all = "camelCase")]
enum RawError<'a> {
Message { status: u16, message: Cow<'a, str> },
}
impl Serialize for LedgerError {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Message { status, message } => RawError::Message {
status: *status,
message: Cow::Borrowed(message),
}
.serialize(serializer),
}
}
}
impl<'de> Deserialize<'de> for LedgerError {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
match RawError::deserialize(deserializer)? {
RawError::Message { status, message } => Ok(Self::Message {
status,
message: message.into_owned(),
}),
}
}
}