From 76e3e6eeba22edd46e4b95e749300319cd280df4 Mon Sep 17 00:00:00 2001 From: gibbz00 Date: Mon, 11 Dec 2023 23:32:56 +0100 Subject: [PATCH] Initial `RopsFile` serialization. --- crates/lib/src/rops_file/core.rs | 69 +++++++++++++++++++ crates/lib/src/rops_file/format/core.rs | 10 +++ crates/lib/src/rops_file/format/mod.rs | 12 ++++ crates/lib/src/rops_file/format/test_utils.rs | 21 ++++++ crates/lib/src/rops_file/format/yaml.rs | 18 +++++ crates/lib/src/rops_file/metadata.rs | 13 ++-- crates/lib/src/rops_file/mod.rs | 6 ++ crates/lib/src/rops_file/tree/yaml.rs | 25 ++++--- crates/lib/src/test_utils/mod.rs | 5 -- crates/lib/src/test_utils/yaml.rs | 21 ------ 10 files changed, 155 insertions(+), 45 deletions(-) create mode 100644 crates/lib/src/rops_file/core.rs create mode 100644 crates/lib/src/rops_file/format/core.rs create mode 100644 crates/lib/src/rops_file/format/mod.rs create mode 100644 crates/lib/src/rops_file/format/test_utils.rs create mode 100644 crates/lib/src/rops_file/format/yaml.rs delete mode 100644 crates/lib/src/test_utils/yaml.rs diff --git a/crates/lib/src/rops_file/core.rs b/crates/lib/src/rops_file/core.rs new file mode 100644 index 0000000..9a17bfc --- /dev/null +++ b/crates/lib/src/rops_file/core.rs @@ -0,0 +1,69 @@ +use serde::{Deserialize, Serialize}; + +use crate::*; + +// TODO: either use typestate or newtype for plaintext and encrypted file differentiation. + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct RopsFile { + #[serde(flatten)] + pub map: F::Map, + #[serde(rename = "sops")] + pub metadata: RopsFileAgeMetadata, +} + +#[cfg(feature = "test-utils")] +mod mock { + use super::*; + + impl MockTestUtil for RopsFile + where + F::Map: MockTestUtil, + { + fn mock() -> Self { + Self { + map: F::Map::mock(), + metadata: MockTestUtil::mock(), + } + } + } + + #[cfg(feature = "yaml")] + mod yaml { + use super::*; + + impl MockFileFormatUtil for RopsFile { + fn mock_format_display() -> String { + indoc::formatdoc! {" + {} + sops: + {}", + ::Map::mock_format_display(), + textwrap::indent(&RopsFileAgeMetadata::mock_format_display()," ") + } + } + } + } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "yaml")] + mod yaml { + use crate::*; + + #[test] + fn serializes_rops_file() { + // TEMP: + println!("{}", RopsFile::::mock_format_display()); + println!("{}", serde_yaml::to_string(&RopsFile::::mock()).unwrap()); + + FileFormatTestUtils::assert_serialization::>() + } + + #[test] + fn deserializes_rops_file() { + FileFormatTestUtils::assert_deserialization::>() + } + } +} diff --git a/crates/lib/src/rops_file/format/core.rs b/crates/lib/src/rops_file/format/core.rs new file mode 100644 index 0000000..d259741 --- /dev/null +++ b/crates/lib/src/rops_file/format/core.rs @@ -0,0 +1,10 @@ +use serde::{de::DeserializeOwned, Serialize}; + +pub trait FileFormat { + type Map; + type SerializeError: std::error::Error + Send + Sync + 'static; + type DeserializeError: std::error::Error + Send + Sync + 'static; + + fn serialize_to_string(t: &T) -> Result; + fn deserialize_from_str(str: &str) -> Result; +} diff --git a/crates/lib/src/rops_file/format/mod.rs b/crates/lib/src/rops_file/format/mod.rs new file mode 100644 index 0000000..594efc8 --- /dev/null +++ b/crates/lib/src/rops_file/format/mod.rs @@ -0,0 +1,12 @@ +mod core; +pub use core::FileFormat; + +#[cfg(feature = "yaml")] +mod yaml; +#[cfg(feature = "yaml")] +pub use yaml::YamlFileFormat; + +#[cfg(feature = "test-utils")] +mod test_utils; +#[cfg(feature = "test-utils")] +pub use test_utils::{FileFormatTestUtils, MockFileFormatUtil}; diff --git a/crates/lib/src/rops_file/format/test_utils.rs b/crates/lib/src/rops_file/format/test_utils.rs new file mode 100644 index 0000000..fe2c727 --- /dev/null +++ b/crates/lib/src/rops_file/format/test_utils.rs @@ -0,0 +1,21 @@ +use std::fmt::Debug; + +use serde::{de::DeserializeOwned, Serialize}; + +use crate::*; + +pub trait MockFileFormatUtil { + fn mock_format_display() -> String; +} + +pub struct FileFormatTestUtils; + +impl FileFormatTestUtils { + pub fn assert_serialization + Serialize>() { + assert_eq!(T::mock_format_display(), F::serialize_to_string(&T::mock()).unwrap()) + } + + pub fn assert_deserialization + DeserializeOwned + Debug + PartialEq>() { + assert_eq!(T::mock(), F::deserialize_from_str(&T::mock_format_display()).unwrap()) + } +} diff --git a/crates/lib/src/rops_file/format/yaml.rs b/crates/lib/src/rops_file/format/yaml.rs new file mode 100644 index 0000000..9bc8fa5 --- /dev/null +++ b/crates/lib/src/rops_file/format/yaml.rs @@ -0,0 +1,18 @@ +use super::*; + +#[derive(Debug, PartialEq)] +pub struct YamlFileFormat; + +impl FileFormat for YamlFileFormat { + type Map = serde_yaml::Mapping; + type SerializeError = serde_yaml::Error; + type DeserializeError = serde_yaml::Error; + + fn serialize_to_string(t: &T) -> Result { + serde_yaml::to_string(t) + } + + fn deserialize_from_str(str: &str) -> Result { + serde_yaml::from_str(str) + } +} diff --git a/crates/lib/src/rops_file/metadata.rs b/crates/lib/src/rops_file/metadata.rs index b7305f8..84e8c4e 100644 --- a/crates/lib/src/rops_file/metadata.rs +++ b/crates/lib/src/rops_file/metadata.rs @@ -44,14 +44,15 @@ mod age { } #[cfg(feature = "yaml")] - impl MockYamlTestUtil for RopsFileAgeMetadata { - fn mock_yaml() -> String { + impl MockFileFormatUtil for RopsFileAgeMetadata { + fn mock_format_display() -> String { indoc::formatdoc! {" recipient: {} enc: | {}", AgeIntegration::mock_public_key_str(), textwrap::indent(AgeIntegration::mock_encrypted_data_key_str()," ") + // textwrap::indent(AgeIntegration::mock_encrypted_data_key_str()," ") } } } @@ -64,13 +65,13 @@ mod age { use crate::*; #[test] - fn serializes_yaml_age_sops_file_metadata() { - YamlTestUtils::assert_serialization::() + fn serializes_rops_file_age_metadata() { + FileFormatTestUtils::assert_serialization::() } #[test] - fn deserializes_yaml_age_sops_file_metadata() { - YamlTestUtils::assert_deserialization::() + fn deserializes_rops_file_age_metadata() { + FileFormatTestUtils::assert_deserialization::() } } } diff --git a/crates/lib/src/rops_file/mod.rs b/crates/lib/src/rops_file/mod.rs index a0ffa59..c7e780e 100644 --- a/crates/lib/src/rops_file/mod.rs +++ b/crates/lib/src/rops_file/mod.rs @@ -6,3 +6,9 @@ pub use tree::{RopsTree, RopsTreeBuildError}; mod metadata; pub use metadata::*; + +mod core; +pub use core::RopsFile; + +mod format; +pub use format::*; diff --git a/crates/lib/src/rops_file/tree/yaml.rs b/crates/lib/src/rops_file/tree/yaml.rs index 0d541a4..9859804 100644 --- a/crates/lib/src/rops_file/tree/yaml.rs +++ b/crates/lib/src/rops_file/tree/yaml.rs @@ -58,29 +58,28 @@ impl TryFrom for RopsTree { mod mock { use super::*; - impl MockYamlTestUtil for YamlMap { - fn mock_yaml() -> String { - " - # Example comment + impl MockFileFormatUtil for YamlMap { + fn mock_format_display() -> String { + indoc::indoc! {" hello: world! nested_map: - null_key: null - array: - - string - - nested_map_in_array: - integer: 1234 - - float: 1234.56789 + null_key: null + array: + - string + - nested_map_in_array: + integer: 1234 + - float: 1234.56789 booleans: - true - - false - " + - false" + } .to_string() } } impl MockTestUtil for YamlMap { fn mock() -> Self { - serde_yaml::from_str(&YamlMap::mock_yaml()).expect("mock yaml string not serializable") + serde_yaml::from_str(&YamlMap::mock_format_display()).expect("mock yaml string not serializable") } } } diff --git a/crates/lib/src/test_utils/mod.rs b/crates/lib/src/test_utils/mod.rs index 843f28b..1691d0f 100644 --- a/crates/lib/src/test_utils/mod.rs +++ b/crates/lib/src/test_utils/mod.rs @@ -6,8 +6,3 @@ pub use display::{DisplayTestUtils, MockDisplayTestUtil}; mod from_str; pub use from_str::FromStrTestUtils; - -#[cfg(feature = "yaml")] -mod yaml; -#[cfg(feature = "yaml")] -pub use yaml::{MockYamlTestUtil, YamlTestUtils}; diff --git a/crates/lib/src/test_utils/yaml.rs b/crates/lib/src/test_utils/yaml.rs deleted file mode 100644 index 696e413..0000000 --- a/crates/lib/src/test_utils/yaml.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::fmt::Debug; - -use serde::{de::DeserializeOwned, Serialize}; - -use crate::*; - -pub trait MockYamlTestUtil { - fn mock_yaml() -> String; -} - -pub struct YamlTestUtils; - -impl YamlTestUtils { - pub fn assert_serialization() { - assert_eq!(T::mock_yaml(), serde_yaml::to_string(&T::mock()).unwrap()) - } - - pub fn assert_deserialization() { - assert_eq!(T::mock(), serde_yaml::from_str(&T::mock_yaml()).unwrap()) - } -}