223 lines
9.1 KiB
Rust
223 lines
9.1 KiB
Rust
//! ## Serializer
|
|
//!
|
|
//! `serializer` is the module which provides the serializer/deserializer for bookmarks
|
|
|
|
/**
|
|
* MIT License
|
|
*
|
|
* termscp - Copyright (c) 2021 Christian Visintin
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
use super::{SerializerError, SerializerErrorKind, UserHosts};
|
|
|
|
use std::io::{Read, Write};
|
|
|
|
pub struct BookmarkSerializer;
|
|
|
|
impl BookmarkSerializer {
|
|
/// ### serialize
|
|
///
|
|
/// Serialize `UserHosts` into TOML and write content to writable
|
|
pub fn serialize(
|
|
&self,
|
|
mut writable: Box<dyn Write>,
|
|
hosts: &UserHosts,
|
|
) -> Result<(), SerializerError> {
|
|
// Serialize content
|
|
let data: String = match toml::ser::to_string(hosts) {
|
|
Ok(dt) => dt,
|
|
Err(err) => {
|
|
return Err(SerializerError::new_ex(
|
|
SerializerErrorKind::SerializationError,
|
|
err.to_string(),
|
|
))
|
|
}
|
|
};
|
|
// Write file
|
|
match writable.write_all(data.as_bytes()) {
|
|
Ok(_) => Ok(()),
|
|
Err(err) => Err(SerializerError::new_ex(
|
|
SerializerErrorKind::IoError,
|
|
err.to_string(),
|
|
)),
|
|
}
|
|
}
|
|
|
|
/// ### deserialize
|
|
///
|
|
/// Read data from readable and deserialize its content as TOML
|
|
pub fn deserialize(&self, mut readable: Box<dyn Read>) -> Result<UserHosts, SerializerError> {
|
|
// Read file content
|
|
let mut data: String = String::new();
|
|
if let Err(err) = readable.read_to_string(&mut data) {
|
|
return Err(SerializerError::new_ex(
|
|
SerializerErrorKind::IoError,
|
|
err.to_string(),
|
|
));
|
|
}
|
|
// Deserialize
|
|
match toml::de::from_str(data.as_str()) {
|
|
Ok(hosts) => Ok(hosts),
|
|
Err(err) => Err(SerializerError::new_ex(
|
|
SerializerErrorKind::SyntaxError,
|
|
err.to_string(),
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
|
|
// Tests
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
use super::super::Bookmark;
|
|
use super::*;
|
|
|
|
use std::collections::HashMap;
|
|
use std::io::{Seek, SeekFrom};
|
|
|
|
#[test]
|
|
fn test_bookmarks_serializer_deserialize_ok() {
|
|
let toml_file: tempfile::NamedTempFile = create_good_toml();
|
|
toml_file.as_file().sync_all().unwrap();
|
|
toml_file.as_file().seek(SeekFrom::Start(0)).unwrap();
|
|
// Parse
|
|
let deserializer: BookmarkSerializer = BookmarkSerializer {};
|
|
let hosts = deserializer.deserialize(Box::new(toml_file));
|
|
assert!(hosts.is_ok());
|
|
let hosts: UserHosts = hosts.ok().unwrap();
|
|
// Verify hosts
|
|
// Verify recents
|
|
assert_eq!(hosts.recents.len(), 1);
|
|
let host: &Bookmark = hosts.recents.get("ISO20201215T094000Z").unwrap();
|
|
assert_eq!(host.address, String::from("172.16.104.10"));
|
|
assert_eq!(host.port, 22);
|
|
assert_eq!(host.protocol, String::from("SCP"));
|
|
assert_eq!(host.username, String::from("root"));
|
|
assert_eq!(host.password, None);
|
|
// Verify bookmarks
|
|
assert_eq!(hosts.bookmarks.len(), 3);
|
|
let host: &Bookmark = hosts.bookmarks.get("raspberrypi2").unwrap();
|
|
assert_eq!(host.address, String::from("192.168.1.31"));
|
|
assert_eq!(host.port, 22);
|
|
assert_eq!(host.protocol, String::from("SFTP"));
|
|
assert_eq!(host.username, String::from("root"));
|
|
assert_eq!(*host.password.as_ref().unwrap(), String::from("mypassword"));
|
|
let host: &Bookmark = hosts.bookmarks.get("msi-estrem").unwrap();
|
|
assert_eq!(host.address, String::from("192.168.1.30"));
|
|
assert_eq!(host.port, 22);
|
|
assert_eq!(host.protocol, String::from("SFTP"));
|
|
assert_eq!(host.username, String::from("cvisintin"));
|
|
assert_eq!(*host.password.as_ref().unwrap(), String::from("mysecret"));
|
|
let host: &Bookmark = hosts.bookmarks.get("aws-server-prod1").unwrap();
|
|
assert_eq!(host.address, String::from("51.23.67.12"));
|
|
assert_eq!(host.port, 21);
|
|
assert_eq!(host.protocol, String::from("FTPS"));
|
|
assert_eq!(host.username, String::from("aws001"));
|
|
assert_eq!(host.password, None);
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmarks_serializer_deserialize_nok() {
|
|
let toml_file: tempfile::NamedTempFile = create_bad_toml();
|
|
toml_file.as_file().sync_all().unwrap();
|
|
toml_file.as_file().seek(SeekFrom::Start(0)).unwrap();
|
|
// Parse
|
|
let deserializer: BookmarkSerializer = BookmarkSerializer {};
|
|
assert!(deserializer.deserialize(Box::new(toml_file)).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_bookmarks_serializer_serialize() {
|
|
let mut bookmarks: HashMap<String, Bookmark> = HashMap::with_capacity(2);
|
|
// Push two samples
|
|
bookmarks.insert(
|
|
String::from("raspberrypi2"),
|
|
Bookmark {
|
|
address: String::from("192.168.1.31"),
|
|
port: 22,
|
|
protocol: String::from("SFTP"),
|
|
username: String::from("root"),
|
|
password: None,
|
|
},
|
|
);
|
|
bookmarks.insert(
|
|
String::from("msi-estrem"),
|
|
Bookmark {
|
|
address: String::from("192.168.1.30"),
|
|
port: 4022,
|
|
protocol: String::from("SFTP"),
|
|
username: String::from("cvisintin"),
|
|
password: Some(String::from("password")),
|
|
},
|
|
);
|
|
let mut recents: HashMap<String, Bookmark> = HashMap::with_capacity(1);
|
|
recents.insert(
|
|
String::from("ISO20201215T094000Z"),
|
|
Bookmark {
|
|
address: String::from("192.168.1.254"),
|
|
port: 3022,
|
|
protocol: String::from("SCP"),
|
|
username: String::from("omar"),
|
|
password: Some(String::from("aaa")),
|
|
},
|
|
);
|
|
let tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
|
// Serialize
|
|
let deserializer: BookmarkSerializer = BookmarkSerializer {};
|
|
let hosts: UserHosts = UserHosts { bookmarks, recents };
|
|
assert!(deserializer.serialize(Box::new(tmpfile), &hosts).is_ok());
|
|
}
|
|
|
|
fn create_good_toml() -> tempfile::NamedTempFile {
|
|
// Write
|
|
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
|
let file_content: &str = r#"
|
|
[bookmarks]
|
|
raspberrypi2 = { address = "192.168.1.31", port = 22, protocol = "SFTP", username = "root", password = "mypassword" }
|
|
msi-estrem = { address = "192.168.1.30", port = 22, protocol = "SFTP", username = "cvisintin", password = "mysecret" }
|
|
aws-server-prod1 = { address = "51.23.67.12", port = 21, protocol = "FTPS", username = "aws001" }
|
|
|
|
[recents]
|
|
ISO20201215T094000Z = { address = "172.16.104.10", port = 22, protocol = "SCP", username = "root" }
|
|
"#;
|
|
tmpfile.write_all(file_content.as_bytes()).unwrap();
|
|
//write!(tmpfile, "[bookmarks]\nraspberrypi2 = {{ address = \"192.168.1.31\", port = 22, protocol = \"SFTP\", username = \"root\" }}\nmsi-estrem = {{ address = \"192.168.1.30\", port = 22, protocol = \"SFTP\", username = \"cvisintin\" }}\naws-server-prod1 = {{ address = \"51.23.67.12\", port = 21, protocol = \"FTPS\", username = \"aws001\" }}\n\n[recents]\nISO20201215T094000Z = {{ address = \"172.16.104.10\", port = 22, protocol = \"SCP\", username = \"root\" }}\n");
|
|
tmpfile
|
|
}
|
|
|
|
fn create_bad_toml() -> tempfile::NamedTempFile {
|
|
// Write
|
|
let mut tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap();
|
|
let file_content: &str = r#"
|
|
[bookmarks]
|
|
raspberrypi2 = { address = "192.168.1.31", port = 22, protocol = "SFTP", username = "root"}
|
|
msi-estrem = { address = "192.168.1.30", port = 22, protocol = "SFTP" }
|
|
aws-server-prod1 = { address = "51.23.67.12", port = 21, protocol = "FTPS", username = "aws001" }
|
|
|
|
[recents]
|
|
ISO20201215T094000Z = { address = "172.16.104.10", protocol = "SCP", username = "root", port = 22 }
|
|
"#;
|
|
tmpfile.write_all(file_content.as_bytes()).unwrap();
|
|
tmpfile
|
|
}
|
|
}
|