diff --git a/src/image/config.rs b/src/image/config.rs index 5a9d7f8b7e..d77e27be30 100644 --- a/src/image/config.rs +++ b/src/image/config.rs @@ -1,7 +1,7 @@ use super::{Arch, Os}; use crate::{ error::{OciSpecError, Result}, - from_file, from_reader, to_file, to_writer, + from_file, from_reader, to_file, to_string, to_writer, }; use derive_builder::Builder; use getset::{CopyGetters, Getters, MutGetters, Setters}; @@ -189,6 +189,47 @@ impl ImageConfiguration { pub fn to_writer_pretty(&self, writer: &mut W) -> Result<()> { to_writer(&self, writer, true) } + + /// Attempts to write an image configuration to a string as JSON. + /// # Errors + /// This function will return an [OciSpecError::SerDe](crate::OciSpecError::SerDe) if + /// the image configuration cannot be serialized. + /// # Example + /// ``` no_run + /// use oci_spec::image::ImageConfiguration; + /// + /// let image_configuration = ImageConfiguration::from_file("config.json").unwrap(); + /// let json_str = image_configuration.to_string().unwrap(); + /// ``` + pub fn to_string(&self) -> Result { + to_string(&self, false) + } + + /// Attempts to write an image configuration to a string as pretty printed JSON. + /// # Errors + /// This function will return an [OciSpecError::SerDe](crate::OciSpecError::SerDe) if + /// the image configuration cannot be serialized. + /// # Example + /// ``` no_run + /// use oci_spec::image::ImageConfiguration; + /// + /// let image_configuration = ImageConfiguration::from_file("config.json").unwrap(); + /// let json_str = image_configuration.to_string_pretty().unwrap(); + /// ``` + pub fn to_string_pretty(&self) -> Result { + to_string(&self, true) + } +} + +/// Implement `ToString` directly since we cannot avoid twice memory allocation +/// when using auto-implementaion through `Display`. +impl ToString for ImageConfiguration { + fn to_string(&self) -> String { + // Serde seralization never fails since this is + // a combination of String and enums. + self.to_string_pretty() + .expect("ImageConfiguration JSON convertion failed") + } } #[derive( @@ -541,4 +582,17 @@ mod tests { let expected = fs::read(get_config_path()).expect("read expected"); assert_eq!(actual, expected); } + + #[test] + fn save_config_to_string() { + // arrange + let config = create_config(); + + // act + let actual = config.to_string_pretty().expect("to string"); + + // assert + let expected = fs::read_to_string(get_config_path()).expect("read expected"); + assert_eq!(actual, expected); + } } diff --git a/src/image/index.rs b/src/image/index.rs index 99e70166a1..82a8d36245 100644 --- a/src/image/index.rs +++ b/src/image/index.rs @@ -1,7 +1,7 @@ use super::{Descriptor, MediaType}; use crate::{ error::{OciSpecError, Result}, - from_file, from_reader, to_file, to_writer, + from_file, from_reader, to_file, to_string, to_writer, }; use derive_builder::Builder; use getset::{CopyGetters, Getters, Setters}; @@ -152,6 +152,36 @@ impl ImageIndex { pub fn to_writer_pretty(&self, writer: &mut W) -> Result<()> { to_writer(&self, writer, true) } + + /// Attempts to write an image index to a string as JSON. + /// # Errors + /// This function will return an [OciSpecError::SerDe](crate::OciSpecError::SerDe) if + /// the image configuration cannot be serialized. + /// # Example + /// ``` no_run + /// use oci_spec::image::ImageIndex; + /// + /// let image_index = ImageIndex::from_file("index.json").unwrap(); + /// let json_str = image_index.to_string().unwrap(); + /// ``` + pub fn to_string(&self) -> Result { + to_string(&self, false) + } + + /// Attempts to write an image index to a string as pretty printed JSON. + /// # Errors + /// This function will return an [OciSpecError::SerDe](crate::OciSpecError::SerDe) if + /// the image configuration cannot be serialized. + /// # Example + /// ``` no_run + /// use oci_spec::image::ImageIndex; + /// + /// let image_index = ImageIndex::from_file("index.json").unwrap(); + /// let json_str = image_index.to_string_pretty().unwrap(); + /// ``` + pub fn to_string_pretty(&self) -> Result { + to_string(&self, true) + } } impl Default for ImageIndex { @@ -165,6 +195,17 @@ impl Default for ImageIndex { } } +/// Implement `ToString` directly since we cannot avoid twice memory allocation +/// when using auto-implementaion through `Display`. +impl ToString for ImageIndex { + fn to_string(&self) -> String { + // Serde seralization never fails since this is + // a combination of String and enums. + self.to_string_pretty() + .expect("ImageIndex to JSON convertion failed") + } +} + #[cfg(test)] mod tests { use std::{fs, path::PathBuf}; @@ -273,4 +314,17 @@ mod tests { let expected = fs::read(get_index_path()).expect("read expected"); assert_eq!(actual, expected); } + + #[test] + fn save_index_to_string() { + // arrange + let index = create_index(); + + // act + let actual = index.to_string_pretty().expect("to string"); + + // assert + let expected = fs::read_to_string(get_index_path()).expect("read expected"); + assert_eq!(actual, expected); + } } diff --git a/src/image/manifest.rs b/src/image/manifest.rs index b44d9653ec..c209c3cbfe 100644 --- a/src/image/manifest.rs +++ b/src/image/manifest.rs @@ -1,7 +1,7 @@ use super::{Descriptor, MediaType}; use crate::{ error::{OciSpecError, Result}, - from_file, from_reader, to_file, to_writer, + from_file, from_reader, to_file, to_string, to_writer, }; use derive_builder::Builder; use getset::{CopyGetters, Getters, MutGetters, Setters}; @@ -174,6 +174,47 @@ impl ImageManifest { pub fn to_writer_pretty(&self, writer: &mut W) -> Result<()> { to_writer(&self, writer, true) } + + /// Attempts to write an image manifest to a string as JSON. + /// # Errors + /// This function will return an [OciSpecError::SerDe](crate::OciSpecError::SerDe) if + /// the image configuration cannot be serialized. + /// # Example + /// ``` no_run + /// use oci_spec::image::ImageManifest; + /// + /// let image_manifest = ImageManifest::from_file("manifest.json").unwrap(); + /// let json_str = image_manifest.to_string().unwrap(); + /// ``` + pub fn to_string(&self) -> Result { + to_string(&self, false) + } + + /// Attempts to write an image manifest to a string as pretty printed JSON. + /// # Errors + /// This function will return an [OciSpecError::SerDe](crate::OciSpecError::SerDe) if + /// the image configuration cannot be serialized. + /// # Example + /// ``` no_run + /// use oci_spec::image::ImageManifest; + /// + /// let image_manifest = ImageManifest::from_file("manifest.json").unwrap(); + /// let json_str = image_manifest.to_string_pretty().unwrap(); + /// ``` + pub fn to_string_pretty(&self) -> Result { + to_string(&self, true) + } +} + +/// Implement `ToString` directly since we cannot avoid twice memory allocation +/// when using auto-implementaion through `Display`. +impl ToString for ImageManifest { + fn to_string(&self) -> String { + // Serde seralization never fails since this is + // a combination of String and enums. + self.to_string_pretty() + .expect("ImageManifest to JSON convertion failed") + } } #[cfg(test)] @@ -299,4 +340,17 @@ mod tests { let expected = fs::read(get_manifest_path()).expect("read expected"); assert_eq!(actual, expected); } + + #[test] + fn save_manifest_to_string() { + // arrange + let manifest = create_manifest(); + + // act + let actual = manifest.to_string_pretty().expect("to string"); + + // assert + let expected = fs::read_to_string(get_manifest_path()).expect("read expected"); + assert_eq!(actual, expected); + } } diff --git a/src/lib.rs b/src/lib.rs index 3052a04edf..6c1990ef7f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,3 +56,10 @@ fn to_writer(item: &T, writer: &mut W, pretty: bool) -> Ok(()) } + +fn to_string(item: &T, pretty: bool) -> Result { + Ok(match pretty { + true => serde_json::to_string_pretty(item)?, + false => serde_json::to_string(item)?, + }) +}