tap_msg/message/
error.rs

1//! Error message type for the Transaction Authorization Protocol.
2//!
3//! This module defines the ErrorBody message type, which is used
4//! to communicate errors in the TAP protocol.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9use crate::error::{Error, Result};
10use crate::TapMessage;
11
12/// Error message body.
13#[derive(Debug, Clone, Serialize, Deserialize, TapMessage)]
14#[tap(generated_id)]
15#[tap(message_type = "https://tap.rsvp/schema/1.0#Error")]
16pub struct ErrorBody {
17    /// Error code.
18    pub code: String,
19
20    /// Error description.
21    pub description: String,
22
23    /// Original message ID (if applicable).
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub original_message_id: Option<String>,
26
27    /// Additional metadata.
28    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
29    pub metadata: HashMap<String, serde_json::Value>,
30}
31
32impl ErrorBody {
33    /// Creates a new ErrorBody message.
34    pub fn new(code: &str, description: &str) -> Self {
35        Self {
36            code: code.to_string(),
37            description: description.to_string(),
38            original_message_id: None,
39            metadata: HashMap::new(),
40        }
41    }
42
43    /// Creates a new ErrorBody message with a reference to the original message.
44    pub fn with_original_message(code: &str, description: &str, original_message_id: &str) -> Self {
45        Self {
46            code: code.to_string(),
47            description: description.to_string(),
48            original_message_id: Some(original_message_id.to_string()),
49            metadata: HashMap::new(),
50        }
51    }
52
53    /// Adds metadata to the error message.
54    pub fn with_metadata(mut self, key: &str, value: serde_json::Value) -> Self {
55        self.metadata.insert(key.to_string(), value);
56        self
57    }
58}
59
60impl ErrorBody {
61    /// Custom validation for ErrorBody messages
62    pub fn validate_error(&self) -> Result<()> {
63        if self.code.is_empty() {
64            return Err(Error::Validation(
65                "Error code is required in ErrorBody".to_string(),
66            ));
67        }
68
69        if self.description.is_empty() {
70            return Err(Error::Validation(
71                "Error description is required in ErrorBody".to_string(),
72            ));
73        }
74
75        Ok(())
76    }
77}