parallel_disk_usage/
json_data.rs

1pub mod binary_version;
2pub mod schema_version;
3
4pub use binary_version::BinaryVersion;
5pub use schema_version::SchemaVersion;
6
7use crate::{
8    data_tree::DataTreeReflection,
9    hardlink::{HardlinkListReflection, SharedLinkSummary},
10    size::{self, Blocks, Bytes},
11};
12use derive_more::{Deref, DerefMut, From, TryInto};
13use smart_default::SmartDefault;
14
15#[cfg(feature = "json")]
16use serde::{Deserialize, Serialize};
17
18/// The `"shared"` field of [`JsonData`].
19#[derive(Debug, SmartDefault, Clone)]
20#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
21#[cfg_attr(feature = "json", serde(rename_all = "kebab-case"))]
22pub struct JsonShared<Size: size::Size> {
23    /// Detailed list of all detected hardlinks.
24    #[cfg_attr(
25        feature = "json",
26        serde(skip_serializing_if = "JsonShared::skip_details")
27    )]
28    pub details: Option<HardlinkListReflection<Size>>,
29    /// Summary of all detected hardlinks.
30    #[cfg_attr(
31        feature = "json",
32        serde(skip_serializing_if = "JsonShared::skip_summary")
33    )]
34    pub summary: Option<SharedLinkSummary<Size>>,
35}
36
37#[cfg(feature = "json")]
38impl<Size: size::Size> JsonShared<Size> {
39    /// Decide whether to skip serializing [`JsonShared::details`].
40    fn skip_details(details: &Option<HardlinkListReflection<Size>>) -> bool {
41        details
42            .as_ref()
43            .is_none_or(|reflection| reflection.is_empty())
44    }
45
46    /// Decide whether to skip serializing [`JsonShared::summary`].
47    fn skip_summary(summary: &Option<SharedLinkSummary<Size>>) -> bool {
48        summary
49            .as_ref()
50            .is_none_or(|summary| summary == &SharedLinkSummary::default())
51    }
52
53    /// Decide whether to skip serializing.
54    fn skip(&self) -> bool {
55        JsonShared::skip_details(&self.details) && JsonShared::skip_summary(&self.summary)
56    }
57}
58
59/// The `"tree"` field and the `"shared"` field of [`JsonData`].
60#[derive(Debug, Clone, Deref, DerefMut)]
61#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
62#[cfg_attr(feature = "json", serde(rename_all = "kebab-case"))]
63pub struct JsonTree<Size: size::Size> {
64    /// The main data of the tree.
65    #[deref]
66    #[deref_mut]
67    pub tree: DataTreeReflection<String, Size>,
68    /// Optional list of shared inodes, their sizes, and their many links.
69    #[cfg_attr(
70        feature = "json",
71        serde(default, skip_serializing_if = "JsonShared::skip")
72    )]
73    pub shared: JsonShared<Size>,
74}
75
76/// The `"unit"` field, the `"tree"` field, and the `"shared-inodes"` field of [`JsonData`].
77#[derive(Debug, Clone, From, TryInto)]
78#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
79#[cfg_attr(feature = "json", serde(tag = "unit"))]
80#[cfg_attr(feature = "json", serde(rename_all = "kebab-case"))]
81pub enum JsonDataBody {
82    /// Tree where size is [bytes](Bytes).
83    Bytes(JsonTree<Bytes>),
84    /// Tree where size is [blocks](Blocks).
85    Blocks(JsonTree<Blocks>),
86}
87
88/// Output of the program with `--json-output` flag as well as
89/// input of the program with `--json-input` flag.
90#[derive(Debug, Clone)]
91#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
92#[cfg_attr(feature = "json", serde(rename_all = "kebab-case"))]
93pub struct JsonData {
94    /// The `"schema-version"` field.
95    pub schema_version: SchemaVersion,
96    /// The `"pdu"` field.
97    #[cfg_attr(feature = "json", serde(rename = "pdu"))]
98    pub binary_version: Option<BinaryVersion>,
99    /// The `"unit"` field, the `"tree"` field, and the `"shared"` field.
100    #[cfg_attr(feature = "json", serde(flatten))]
101    pub body: JsonDataBody,
102}