rustdoc/html/render/
ordered_json.rsuse std::borrow::Borrow;
use std::fmt;
use itertools::Itertools as _;
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(from = "Value")]
#[serde(into = "Value")]
pub(crate) struct OrderedJson(String);
impl OrderedJson {
pub(crate) fn serialize<T: Serialize>(item: T) -> Result<Self, serde_json::Error> {
Ok(Self(serde_json::to_string(&item)?))
}
pub(crate) fn array_sorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self {
let items = items
.into_iter()
.sorted_unstable_by(|a, b| a.borrow().cmp(&b.borrow()))
.format_with(",", |item, f| f(item.borrow()));
Self(format!("[{}]", items))
}
pub(crate) fn array_unsorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self {
let items = items.into_iter().format_with(",", |item, f| f(item.borrow()));
Self(format!("[{items}]"))
}
}
impl fmt::Display for OrderedJson {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl From<Value> for OrderedJson {
fn from(value: Value) -> Self {
let serialized =
serde_json::to_string(&value).expect("Serializing a Value to String should never fail");
Self(serialized)
}
}
impl From<OrderedJson> for Value {
fn from(json: OrderedJson) -> Self {
serde_json::from_str(&json.0).expect("OrderedJson should always store valid JSON")
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct EscapedJson(OrderedJson);
impl From<OrderedJson> for EscapedJson {
fn from(json: OrderedJson) -> Self {
Self(json)
}
}
impl fmt::Display for EscapedJson {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let json = self.0.0.replace('\\', r"\\").replace('\'', r"\'").replace("\\\"", "\\\\\"");
json.fmt(f)
}
}
#[cfg(test)]
mod tests;