Finalize serialization and deserialization
This commit is contained in:
parent
80bb5bbb22
commit
62cf06cf1e
@ -3,8 +3,10 @@
|
|||||||
use num_traits::identities::One;
|
use num_traits::identities::One;
|
||||||
use num_traits::identities::Zero;
|
use num_traits::identities::Zero;
|
||||||
use serde::de;
|
use serde::de;
|
||||||
|
use serde::Serializer;
|
||||||
// use serde::de::Error;
|
// use serde::de::Error;
|
||||||
use serde::de::Visitor;
|
use serde::de::Visitor;
|
||||||
|
use serde::ser::SerializeSeq;
|
||||||
use serde_repr::Deserialize_repr;
|
use serde_repr::Deserialize_repr;
|
||||||
use serde_repr::Serialize_repr;
|
use serde_repr::Serialize_repr;
|
||||||
use std::ops::Not;
|
use std::ops::Not;
|
||||||
@ -16,15 +18,28 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
// This is based on https://dev.yorhel.nl/ncdu/jsonfmt
|
// This is based on https://dev.yorhel.nl/ncdu/jsonfmt
|
||||||
|
|
||||||
#[derive(Serialize, Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
struct NcduFile {
|
struct NcduFile {
|
||||||
pub major_version: MajorVersion,
|
pub major_version: MajorVersion,
|
||||||
pub minor_version: MinorVersion,
|
pub minor_version: MinorVersion,
|
||||||
pub header_metadata: HeaderMetadata,
|
pub header_metadata: HeaderMetadata,
|
||||||
#[serde(flatten)]
|
|
||||||
pub contents: Directory,
|
pub contents: Directory,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for NcduFile {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let mut seq = serializer.serialize_seq(Some(4))?;
|
||||||
|
seq.serialize_element(&self.major_version)?;
|
||||||
|
seq.serialize_element(&self.minor_version)?;
|
||||||
|
seq.serialize_element(&self.header_metadata)?;
|
||||||
|
seq.serialize_element(&self.contents)?;
|
||||||
|
seq.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for NcduFile {
|
impl<'de> Deserialize<'de> for NcduFile {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@ -123,13 +138,34 @@ impl HeaderMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Directory {
|
pub struct Directory {
|
||||||
info: InfoBlock,
|
info: InfoBlock,
|
||||||
#[serde(flatten)]
|
|
||||||
contents: Vec<FileOrDirectory>,
|
contents: Vec<FileOrDirectory>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for Directory {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
use serde::ser::Error;
|
||||||
|
let mut seq = serializer.serialize_seq(Some(
|
||||||
|
self.contents
|
||||||
|
.len()
|
||||||
|
.checked_add(1)
|
||||||
|
.ok_or_else(|| S::Error::custom("Directory contents too large"))?,
|
||||||
|
))?;
|
||||||
|
// Add the info block first
|
||||||
|
seq.serialize_element(&self.info)?;
|
||||||
|
// Then any entries
|
||||||
|
for element in self.contents.iter() {
|
||||||
|
seq.serialize_element(element)?;
|
||||||
|
}
|
||||||
|
seq.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Directory {
|
impl<'de> Deserialize<'de> for Directory {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@ -200,6 +236,7 @@ pub struct InfoBlock {
|
|||||||
/// Device ID. A unique ID within the context of the exported dump. Could be a serialization of lstat().st_dev, but could be randomly generated and used within this file
|
/// Device ID. A unique ID within the context of the exported dump. Could be a serialization of lstat().st_dev, but could be randomly generated and used within this file
|
||||||
///
|
///
|
||||||
/// Accepted values are in the range of 0 <= dev < 2^64.
|
/// Accepted values are in the range of 0 <= dev < 2^64.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
pub dev: Option<DeviceId>,
|
pub dev: Option<DeviceId>,
|
||||||
|
|
||||||
/// Apparent filesize
|
/// Apparent filesize
|
||||||
@ -261,17 +298,22 @@ pub struct InfoBlock {
|
|||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct ExtendedInfoBlock {
|
pub struct ExtendedInfoBlock {
|
||||||
/// Number, user ID who owns the file. Accepted values are in the range 0 <= uid < 2^31.
|
/// Number, user ID who owns the file. Accepted values are in the range 0 <= uid < 2^31.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
uid: Option<u32>,
|
uid: Option<u32>,
|
||||||
/// Number, group ID who owns the file. Accepted values are in the range 0 <= uid < 2^31.
|
/// Number, group ID who owns the file. Accepted values are in the range 0 <= uid < 2^31.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
gid: Option<u32>,
|
gid: Option<u32>,
|
||||||
/// Number, the raw file mode as returned by lstat(3). For Linux systems, see inode(7) for the interpretation of this field. Accepted range: 0 <= mode < 2^16.
|
/// Number, the raw file mode as returned by lstat(3). For Linux systems, see inode(7) for the interpretation of this field. Accepted range: 0 <= mode < 2^16.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
mode: Option<u16>,
|
mode: Option<u16>,
|
||||||
/// Number, last modification time as a UNIX timestamp. Accepted range: 0 <= mtime < 2^64. As of ncdu 1.16, this number may also include an (infinite precision) decimal part for fractional seconds, though the decimal part is (currently) discarded during import.
|
/// Number, last modification time as a UNIX timestamp. Accepted range: 0 <= mtime < 2^64. As of ncdu 1.16, this number may also include an (infinite precision) decimal part for fractional seconds, though the decimal part is (currently) discarded during import.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none", default)]
|
||||||
mtime: Option<u64>,
|
mtime: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use serde_path_to_error;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -354,7 +396,6 @@ mod tests {
|
|||||||
.is_ok());
|
.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
use serde_path_to_error;
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple_ncdu_output() {
|
fn test_simple_ncdu_output() {
|
||||||
let input = fs::read_to_string("../sample-ncdu-output.json").unwrap();
|
let input = fs::read_to_string("../sample-ncdu-output.json").unwrap();
|
||||||
@ -365,7 +406,6 @@ mod tests {
|
|||||||
e
|
e
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// let parsed = serde_path_to_error::from_str::<NcduFile>(&input).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(parsed.major_version, MajorVersion::Version1);
|
assert_eq!(parsed.major_version, MajorVersion::Version1);
|
||||||
assert_eq!(parsed.minor_version, MinorVersion::Minor2);
|
assert_eq!(parsed.minor_version, MinorVersion::Minor2);
|
||||||
@ -373,4 +413,17 @@ mod tests {
|
|||||||
assert_eq!(parsed.contents.info.name, "/tmp/tmp.2gWrgcHU4X");
|
assert_eq!(parsed.contents.info.name, "/tmp/tmp.2gWrgcHU4X");
|
||||||
assert_eq!(parsed.contents.contents.len(), 2);
|
assert_eq!(parsed.contents.contents.len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serialization() {
|
||||||
|
let input = fs::read_to_string("../sample-ncdu-output.json").unwrap();
|
||||||
|
let deserialized = serde_json::from_str::<NcduFile>(&input).unwrap();
|
||||||
|
let serialized = serde_json::to_string(&deserialized).unwrap();
|
||||||
|
let deserialized_again = serde_json::from_str::<NcduFile>(&serialized).unwrap();
|
||||||
|
let serialized_again = serde_json::to_string(&deserialized_again).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(serialized, serialized_again);
|
||||||
|
assert_eq!(deserialized, deserialized_again);
|
||||||
|
assert_eq!(serialized, input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user