rustdoc/html/render/
ordered_json.rs
1use std::borrow::Borrow;
2use std::fmt;
3
4use itertools::Itertools as _;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
12#[serde(from = "Value")]
13#[serde(into = "Value")]
14pub(crate) struct OrderedJson(String);
15
16impl OrderedJson {
17 pub(crate) fn serialize<T: Serialize>(item: T) -> Result<Self, serde_json::Error> {
19 Ok(Self(serde_json::to_string(&item)?))
20 }
21
22 pub(crate) fn array_sorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self {
24 let items = items
25 .into_iter()
26 .sorted_unstable_by(|a, b| a.borrow().cmp(b.borrow()))
27 .format_with(",", |item, f| f(item.borrow()));
28 Self(format!("[{}]", items))
29 }
30
31 pub(crate) fn array_unsorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self {
32 let items = items.into_iter().format_with(",", |item, f| f(item.borrow()));
33 Self(format!("[{items}]"))
34 }
35}
36
37impl fmt::Display for OrderedJson {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 self.0.fmt(f)
40 }
41}
42
43impl From<Value> for OrderedJson {
44 fn from(value: Value) -> Self {
45 let serialized =
46 serde_json::to_string(&value).expect("Serializing a Value to String should never fail");
47 Self(serialized)
48 }
49}
50
51impl From<OrderedJson> for Value {
52 fn from(json: OrderedJson) -> Self {
53 serde_json::from_str(&json.0).expect("OrderedJson should always store valid JSON")
54 }
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
64pub(crate) struct EscapedJson(OrderedJson);
65
66impl From<OrderedJson> for EscapedJson {
67 fn from(json: OrderedJson) -> Self {
68 Self(json)
69 }
70}
71
72impl fmt::Display for EscapedJson {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 let json = self.0.0.replace('\\', r"\\").replace('\'', r"\'").replace("\\\"", "\\\\\"");
78 json.fmt(f)
79 }
80}
81
82#[cfg(test)]
83mod tests;