Skip to content

Commit

Permalink
Initial RopsFile serialization.
Browse files Browse the repository at this point in the history
  • Loading branch information
gibbz00 committed Dec 11, 2023
1 parent c6e25ef commit 76e3e6e
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 45 deletions.
69 changes: 69 additions & 0 deletions crates/lib/src/rops_file/core.rs
Original file line number Diff line number Diff line change
@@ -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<F: FileFormat> {
#[serde(flatten)]
pub map: F::Map,
#[serde(rename = "sops")]
pub metadata: RopsFileAgeMetadata,
}

#[cfg(feature = "test-utils")]
mod mock {
use super::*;

impl<F: FileFormat> MockTestUtil for RopsFile<F>
where
F::Map: MockTestUtil,
{
fn mock() -> Self {
Self {
map: F::Map::mock(),
metadata: MockTestUtil::mock(),
}
}
}

#[cfg(feature = "yaml")]
mod yaml {
use super::*;

impl MockFileFormatUtil<YamlFileFormat> for RopsFile<YamlFileFormat> {
fn mock_format_display() -> String {
indoc::formatdoc! {"
{}
sops:
{}",
<YamlFileFormat as FileFormat>::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::<YamlFileFormat>::mock_format_display());
println!("{}", serde_yaml::to_string(&RopsFile::<YamlFileFormat>::mock()).unwrap());

FileFormatTestUtils::assert_serialization::<YamlFileFormat, RopsFile<YamlFileFormat>>()
}

#[test]
fn deserializes_rops_file() {
FileFormatTestUtils::assert_deserialization::<YamlFileFormat, RopsFile<YamlFileFormat>>()
}
}
}
10 changes: 10 additions & 0 deletions crates/lib/src/rops_file/format/core.rs
Original file line number Diff line number Diff line change
@@ -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: Serialize>(t: &T) -> Result<String, Self::SerializeError>;
fn deserialize_from_str<T: DeserializeOwned>(str: &str) -> Result<T, Self::DeserializeError>;
}
12 changes: 12 additions & 0 deletions crates/lib/src/rops_file/format/mod.rs
Original file line number Diff line number Diff line change
@@ -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};
21 changes: 21 additions & 0 deletions crates/lib/src/rops_file/format/test_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use std::fmt::Debug;

use serde::{de::DeserializeOwned, Serialize};

use crate::*;

pub trait MockFileFormatUtil<F: FileFormat> {
fn mock_format_display() -> String;
}

pub struct FileFormatTestUtils;

impl FileFormatTestUtils {
pub fn assert_serialization<F: FileFormat, T: MockTestUtil + MockFileFormatUtil<F> + Serialize>() {
assert_eq!(T::mock_format_display(), F::serialize_to_string(&T::mock()).unwrap())
}

pub fn assert_deserialization<F: FileFormat, T: MockTestUtil + MockFileFormatUtil<F> + DeserializeOwned + Debug + PartialEq>() {
assert_eq!(T::mock(), F::deserialize_from_str(&T::mock_format_display()).unwrap())
}
}
18 changes: 18 additions & 0 deletions crates/lib/src/rops_file/format/yaml.rs
Original file line number Diff line number Diff line change
@@ -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: serde::Serialize>(t: &T) -> Result<String, Self::SerializeError> {
serde_yaml::to_string(t)
}

fn deserialize_from_str<T: serde::de::DeserializeOwned>(str: &str) -> Result<T, Self::DeserializeError> {
serde_yaml::from_str(str)
}
}
13 changes: 7 additions & 6 deletions crates/lib/src/rops_file/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,15 @@ mod age {
}

#[cfg(feature = "yaml")]
impl MockYamlTestUtil for RopsFileAgeMetadata {
fn mock_yaml() -> String {
impl MockFileFormatUtil<YamlFileFormat> 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()," ")
}
}
}
Expand All @@ -64,13 +65,13 @@ mod age {
use crate::*;

#[test]
fn serializes_yaml_age_sops_file_metadata() {
YamlTestUtils::assert_serialization::<RopsFileAgeMetadata>()
fn serializes_rops_file_age_metadata() {
FileFormatTestUtils::assert_serialization::<YamlFileFormat, RopsFileAgeMetadata>()
}

#[test]
fn deserializes_yaml_age_sops_file_metadata() {
YamlTestUtils::assert_deserialization::<RopsFileAgeMetadata>()
fn deserializes_rops_file_age_metadata() {
FileFormatTestUtils::assert_deserialization::<YamlFileFormat, RopsFileAgeMetadata>()
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions crates/lib/src/rops_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
25 changes: 12 additions & 13 deletions crates/lib/src/rops_file/tree/yaml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,28 @@ impl TryFrom<YamlMap> for RopsTree {
mod mock {
use super::*;

impl MockYamlTestUtil for YamlMap {
fn mock_yaml() -> String {
"
# Example comment
impl MockFileFormatUtil<YamlFileFormat> 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")
}
}
}
Expand Down
5 changes: 0 additions & 5 deletions crates/lib/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
21 changes: 0 additions & 21 deletions crates/lib/src/test_utils/yaml.rs

This file was deleted.

0 comments on commit 76e3e6e

Please sign in to comment.