use crate::ErrFrame;
use serde::{Serialize, Serializer};
use serde_json::Value;
use std::collections::HashMap;
impl Serialize for ErrFrame {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeMap;
let mut map = serializer.serialize_map(None)?;
map.serialize_entry("message", self.message())?;
if !self.context.is_empty() {
let context: HashMap<String, String> = self
.context
.iter()
.filter_map(|layer| {
layer
.key()
.map(|k| (k.to_string(), layer.value().as_str().to_string()))
})
.collect();
if !context.is_empty() {
map.serialize_entry("context", &context)?;
}
let text_context: Vec<String> = self
.context
.iter()
.filter(|layer| layer.key().is_none())
.map(|layer| layer.value().as_str().to_string())
.collect();
if !text_context.is_empty() {
map.serialize_entry("notes", &text_context)?;
}
}
#[cfg(feature = "std")]
if let Some(source) = self.source.as_ref() {
map.serialize_entry("source", &source.to_string())?;
}
map.end()
}
}
impl ErrFrame {
pub fn to_json(&self) -> Value {
serde_json::to_value(self).unwrap_or_else(|_| {
serde_json::json!({
"message": self.message(),
"error": "Failed to serialize error"
})
})
}
pub fn to_json_string(&self) -> String {
serde_json::to_string_pretty(&self.to_json())
.unwrap_or_else(|_| format!("{{\"message\": \"{}\"}}", self.message()))
}
#[cfg(feature = "markdown")]
pub fn to_markdown(&self) -> String {
let mut output = String::new();
output.push_str("# Error\n\n");
output.push_str(&format!("**{}**\n\n", self.message()));
if !self.context.is_empty() {
output.push_str("## Context\n\n");
for layer in self.context.iter() {
if let Some(key) = layer.key() {
output.push_str(&format!("- **{}**: {}\n", key, layer.value().as_str()));
} else {
output.push_str(&format!("- {}\n", layer.value().as_str()));
}
}
output.push('\n');
}
#[cfg(feature = "std")]
if let Some(source) = self.source.as_ref() {
output.push_str("## Cause\n\n");
output.push_str(&format!("```\n{}\n```\n", source));
}
output
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_to_json() {
let err = ErrFrame::new("test error").context("key", "value");
let json = err.to_json();
assert!(json["message"].as_str().unwrap().contains("test"));
}
#[test]
fn test_to_json_string() {
let err = ErrFrame::new("test error");
let json_str = err.to_json_string();
assert!(json_str.contains("test error"));
}
#[cfg(feature = "markdown")]
#[test]
fn test_to_markdown() {
let err = ErrFrame::new("test error").context("key", "value");
let md = err.to_markdown();
assert!(md.contains("# Error"));
assert!(md.contains("test error"));
}
}