lusl/
lib.rs

1//!
2//! # Lossless Uncompressed Serializer Library
3//!
4//! `lusl` is a library that serializes a directory containing multiple files into a single file and also deserializes it, like a tarball.
5//!
6//! This library also provides a way to encrypt and compress the serialized file.
7//!
8//! The encryption is done using [XChaCha20-Poly1305](https://en.wikipedia.org/wiki/ChaCha20-Poly1305#XChaCha20-Poly1305_%E2%80%93_extended_nonce_variant)
9//! and the compression is done using [zlib](https://en.wikipedia.org/wiki/Zlib).
10//!
11//! It also saves [MD5](md5) checksums when serializing files and verify it when deserializing file for data integrity.
12//!
13//! ## Usage
14//!
15//! ### Serializing and deserializing without encrypting or compressing.
16//! ```rust
17//! use lusl::{Serializer, Deserializer, SerializeOption};
18//! use std::path::PathBuf;
19//!
20//! // Serialize a directory into a file.
21//! let original = PathBuf::from("tests");
22//! let result = PathBuf::from("serialized.bin");
23//! let mut serializer = Serializer::new(&original, &result).unwrap();
24//! serializer.serialize().unwrap();
25//!
26//! // Deserialize the file into a directory.
27//! let restored = PathBuf::from("deserialized_dir");
28//! let mut deserializer = Deserializer::new(&result, &restored).unwrap();
29//! deserializer.deserialize().unwrap();
30//!
31//! assert!(&result.is_file());
32//! assert!(&restored.is_dir());
33//! ```
34//!
35//! ### Serializing and deserializing with encrypting and compressing.
36//! ```rust
37//! use lusl::{Serializer, Deserializer, SerializeOption};
38//! use std::path::PathBuf;
39//!
40//! // Serialize a directory into a file.
41//! let original = PathBuf::from("tests");
42//! let result = PathBuf::from("serialized.bin");
43//! let mut serializer = Serializer::new(&original, &result).unwrap();
44//!
45//! // Set the encryption key and compression option.
46//! serializer.set_option(SerializeOption::new().to_encrypt("password").to_compress(true));
47//! serializer.serialize().unwrap();
48//!
49//! // Deserialize the file into a directory.
50//! let restored = PathBuf::from("deserialized_dir");
51//! let mut deserializer = Deserializer::new(&result, &restored).unwrap();
52//!
53//! // Set the encryption key and compression option.
54//! deserializer.set_option(SerializeOption::new().to_encrypt("password").to_compress(true));
55//! deserializer.deserialize().unwrap();
56//!
57//! assert!(&result.is_file());
58//! assert!(&restored.is_dir());
59//! ```
60//!
61
62mod binary;
63mod compress;
64mod encrypt;
65mod serialize;
66
67use std::fs::File;
68use std::io::{self, Read};
69use std::path::Path;
70
71pub use serialize::deserializer::Deserializer;
72use serialize::header::{FILE_LABEL, VERSION_START_POINTER};
73pub use serialize::option::SerializeOption;
74pub use serialize::serializer::Serializer;
75pub use serialize::version;
76
77/// Reads the version of the serialized file.
78/// # Errors
79/// This function will return an error if the file is not a serialized file or the version is invalid.
80/// # Examples
81/// ```rust
82/// use std::path::PathBuf;
83/// use lusl::read_version;
84/// use lusl::{Serializer, Deserializer};
85/// use lusl::version::{Version, get_major_version, get_minor_version, get_patch_version};
86///
87/// // create a new serialized file.
88/// let original = PathBuf::from("tests");
89/// let result = PathBuf::from("serialized.bin");
90/// let mut serializer = Serializer::new(&original, &result).unwrap();
91/// serializer.serialize().unwrap();
92///
93/// // read the version of the serialized file.
94/// let version = read_version(&result).unwrap();
95/// assert_eq!(get_major_version(), version.major());
96/// assert_eq!(get_minor_version(), version.minor());
97/// assert_eq!(get_patch_version(), version.patch());
98///
99/// ```
100pub fn read_version<T: AsRef<Path>>(filepath: T) -> io::Result<version::Version> {
101    let mut file = File::open(filepath)?;
102    let mut buffer: Vec<u8> = Vec::with_capacity(FILE_LABEL.len());
103    buffer.resize(FILE_LABEL.len(), 0);
104    file.read(&mut buffer)?;
105    let mut version_buffer: Vec<u8> = Vec::with_capacity(4);
106    version_buffer.resize(4, 0);
107    file.read(&mut version_buffer)?;
108    if version_buffer[0] != VERSION_START_POINTER {
109        return Err(io::Error::new(
110            io::ErrorKind::InvalidData,
111            "Invalid version format",
112        ));
113    }
114    let version = version::Version::from_bytes(&version_buffer[1..4])?;
115    Ok(version)
116}
117
118#[cfg(test)]
119mod tests {
120    use crate::serialize::version::{get_major_version, get_minor_version, get_patch_version};
121
122    use super::*;
123    use std::{fs, path::PathBuf};
124
125    #[test]
126    fn test_read_version() {
127        // create a new serialized file.
128        let original = PathBuf::from("tests");
129        let result = PathBuf::from("serialized.bin");
130        let mut serializer = Serializer::new(&original, &result).unwrap();
131        serializer.serialize().unwrap();
132
133        // read version of it.
134        let version = read_version(&result).unwrap();
135        assert_eq!(
136            version,
137            version::Version::new(
138                get_major_version(),
139                get_minor_version(),
140                get_patch_version()
141            )
142        );
143
144        // delete the file.
145        fs::remove_file(&result).unwrap();
146    }
147}