use bc_ur::{UR, URDecodable, UREncodable};
use serde::{Deserialize, Deserializer, Serialize};
use crate::{
ProvenanceMark,
util::{deserialize_ur, serialize_ur},
};
#[derive(Serialize, Clone)]
pub struct ProvenanceMarkInfo {
#[serde(
serialize_with = "serialize_ur",
deserialize_with = "deserialize_ur"
)]
ur: UR,
bytewords: String,
bytemoji: String,
#[serde(default, skip_serializing_if = "String::is_empty")]
comment: String,
mark: ProvenanceMark,
}
impl<'de> Deserialize<'de> for ProvenanceMarkInfo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct ProvenanceMarkInfoHelper {
#[serde(
serialize_with = "serialize_ur",
deserialize_with = "deserialize_ur"
)]
ur: UR,
bytewords: String,
bytemoji: String,
#[serde(default)]
comment: String,
#[serde(default)]
#[allow(dead_code)]
mark: Option<serde_json::Value>,
}
let helper = ProvenanceMarkInfoHelper::deserialize(deserializer)?;
let mark = ProvenanceMark::from_ur(&helper.ur)
.map_err(serde::de::Error::custom)?;
Ok(ProvenanceMarkInfo {
ur: helper.ur,
bytewords: helper.bytewords,
bytemoji: helper.bytemoji,
comment: helper.comment,
mark,
})
}
}
impl ProvenanceMarkInfo {
pub fn new(mark: ProvenanceMark, comment: impl Into<String>) -> Self {
let ur = mark.ur();
let bytewords = mark.id_bytewords(4, true);
let bytemoji = mark.id_bytemoji(4, true);
let comment = comment.into();
Self { mark, ur, bytewords, bytemoji, comment }
}
pub fn mark(&self) -> &ProvenanceMark { &self.mark }
pub fn ur(&self) -> &UR { &self.ur }
pub fn bytewords(&self) -> &str { &self.bytewords }
pub fn bytemoji(&self) -> &str { &self.bytemoji }
pub fn comment(&self) -> &str { &self.comment }
pub fn markdown_summary(&self) -> String {
let mut lines: Vec<String> = Vec::new();
lines.push("---".to_string());
lines.push("".to_string());
lines.push(format!("{}", self.mark.date()));
lines.push("".to_string());
lines.push(format!("#### {}", self.ur));
lines.push("".to_string());
lines.push(format!("#### `{}`", self.bytewords));
lines.push("".to_string());
lines.push(self.bytemoji.clone().to_string());
lines.push("".to_string());
if !self.comment.is_empty() {
lines.push(self.comment.clone());
lines.push("".to_string());
}
lines.join("\n")
}
}