systemprompt_models/api/errors/
wire.rs1use chrono::{DateTime, Utc};
7use serde::{Serialize, Serializer};
8use systemprompt_identifiers::TraceId;
9
10use super::{ApiError, ErrorCode, ValidationError};
11
12#[derive(Serialize)]
13struct WireApiError<'a> {
14 code: ErrorCode,
15 message: &'a str,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 details: Option<&'a str>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 error_key: Option<&'a str>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 path: Option<&'a str>,
22 #[serde(skip_serializing_if = "no_validation_errors")]
23 validation_errors: &'a [ValidationError],
24 timestamp: DateTime<Utc>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 trace_id: Option<&'a TraceId>,
27}
28
29const fn no_validation_errors(errors: &&[ValidationError]) -> bool {
30 errors.is_empty()
31}
32
33impl Serialize for ApiError {
34 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
35 let server_error = self.code.is_server_error();
36 let message: &str = if server_error {
37 self.code.public_server_message()
38 } else {
39 self.message.as_str()
40 };
41 let details = if server_error {
42 None
43 } else {
44 self.details.as_deref()
45 };
46 let validation_errors: &[ValidationError] = if server_error {
47 <&[ValidationError]>::default()
48 } else {
49 self.validation_errors.as_slice()
50 };
51 WireApiError {
52 code: self.code,
53 message,
54 details,
55 error_key: self.error_key.as_deref(),
56 path: self.path.as_deref(),
57 validation_errors,
58 timestamp: self.timestamp,
59 trace_id: self.trace_id.as_ref(),
60 }
61 .serialize(serializer)
62 }
63}