1use std::fmt;
18use serde::{Deserialize, Serialize};
20
21use crate::failure::{Failure, Origin};
23use crate::operations;
24
25pub const RESERVED: &str = "harmos.";
28
29pub const FAILED: i64 = -32_000;
30
31pub const UNKNOWN: i64 = -32_601;
32
33pub const UNREADABLE: i64 = -32_602;
34
35#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
43#[serde(deny_unknown_fields)]
44pub struct Refusal {
45 code: i64,
46 failure: Failure,
47}
48
49impl Refusal {
56 pub fn new(code: i64, message: impl fmt::Display) -> Self {
57 let failure = Failure::new(operations::FailureKind::Permanent, message.to_string());
58 Self::failed(code, failure)
59 }
60
61 pub fn of(cause: impl fmt::Display) -> Self {
62 Self::new(FAILED, cause)
63 }
64
65 pub fn failed(code: i64, failure: Failure) -> Self {
66 Self { code, failure }
67 }
68
69 pub fn originate(
71 code: i64, classification: operations::FailureKind, error: &(dyn std::error::Error + 'static), origin: Origin,
72 ) -> Self {
73 Self::failed(code, Failure::originate(classification, error, origin))
74 }
75
76 pub fn code(&self) -> i64 {
77 self.code
78 }
79
80 pub fn message(&self) -> &str {
81 self.failure.cause()
82 }
83
84 pub fn failure(&self) -> &Failure {
85 &self.failure
86 }
87
88 pub fn into_failure(self) -> Failure {
89 self.failure
90 }
91}
92
93impl fmt::Display for Refusal {
94 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
95 match self.failure.context().operation() {
97 Some(operation) => write!(formatter, "operation `{operation}` failed: {} ({})", self.failure.cause(), self.code),
98 None => write!(formatter, "{} ({})", self.failure.cause(), self.code),
99 }
100 }
101}
102
103impl std::error::Error for Refusal {}
104
105pub const fn reserved(method: &str) -> bool {
108 let bytes = method.as_bytes();
109 bytes.len() >= 7
110 && bytes[0] == b'h'
111 && bytes[1] == b'a'
112 && bytes[2] == b'r'
113 && bytes[3] == b'm'
114 && bytes[4] == b'o'
115 && bytes[5] == b's'
116 && (bytes[6] == b'.' || bytes[6] == b'_')
117}
118
119