use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FieldViolation {
pub field: String,
pub description: String,
}
impl FieldViolation {
pub fn new(field: impl Into<String>, description: impl Into<String>) -> Self {
Self {
field: field.into(),
description: description.into(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ErrorInfo {
pub reason: String,
pub domain: String,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub metadata: BTreeMap<String, String>,
}
impl ErrorInfo {
pub fn new(reason: impl Into<String>) -> Self {
Self {
reason: reason.into(),
domain: DOMAIN.to_string(),
metadata: BTreeMap::new(),
}
}
pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.metadata.insert(key.into(), value.into());
self
}
}
pub const DOMAIN: &str = "a2a-rs";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "@type")]
pub enum ErrorDetail {
#[serde(rename = "type.googleapis.com/google.rpc.BadRequest")]
BadRequest {
#[serde(rename = "fieldViolations")]
field_violations: Vec<FieldViolation>,
},
#[serde(rename = "type.googleapis.com/google.rpc.ErrorInfo")]
ErrorInfo(ErrorInfo),
}
impl ErrorDetail {
pub fn bad_request(field: impl Into<String>, description: impl Into<String>) -> Self {
Self::BadRequest {
field_violations: vec![FieldViolation::new(field, description)],
}
}
pub fn reason(reason: impl Into<String>) -> Self {
Self::ErrorInfo(ErrorInfo::new(reason))
}
}