shadow_crypt_shell/
utils.rs1use std::io::Read;
2
3use shadow_crypt_core::memory::{SecureBytes, SecureString};
4
5use crate::errors::{WorkflowError, WorkflowResult};
6
7pub fn read_n_bytes_from_file(path: &std::path::Path, n: usize) -> WorkflowResult<SecureBytes> {
8 let f = std::fs::File::open(path)?;
9 let mut buffer = Vec::new();
10 f.take(n as u64).read_to_end(&mut buffer)?;
11
12 Ok(SecureBytes::new(buffer))
13}
14
15pub fn parse_string_from_bytes(bytes: &SecureBytes) -> WorkflowResult<SecureString> {
16 match String::from_utf8(bytes.as_slice().to_vec()) {
17 Ok(s) => Ok(SecureString::new(s)),
18 Err(_) => Err(WorkflowError::Parse(
19 "Failed to decode string from bytes".to_string(),
20 )),
21 }
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27 use std::io::Write;
28 use tempfile::NamedTempFile;
29
30 #[test]
31 fn test_parse_string_from_bytes_valid() {
32 let input_bytes = SecureBytes::new(b"test_filename.txt".to_vec());
33 let result = parse_string_from_bytes(&input_bytes).unwrap();
34 assert_eq!(result.as_str(), "test_filename.txt");
35 }
36
37 #[test]
38 fn test_parse_string_from_bytes_invalid() {
39 let input_bytes = SecureBytes::new(vec![0xff, 0xfe, 0xfd]);
40 let result = parse_string_from_bytes(&input_bytes);
41 assert!(result.is_err());
42 if let Err(WorkflowError::Parse(msg)) = result {
43 assert_eq!(msg, "Failed to decode string from bytes");
44 } else {
45 panic!("Expected Parse error");
46 }
47 }
48
49 #[test]
50 fn test_read_n_bytes_from_file_exact() {
51 let mut temp_file = NamedTempFile::new().unwrap();
52 let data = b"hello world";
53 temp_file.write_all(data).unwrap();
54 let path = temp_file.path();
55
56 let result = read_n_bytes_from_file(path, 11).unwrap();
57 assert_eq!(result.as_slice(), data);
58 }
59
60 #[test]
61 fn test_read_n_bytes_from_file_more_than_available() {
62 let mut temp_file = NamedTempFile::new().unwrap();
63 let data = b"hello";
64 temp_file.write_all(data).unwrap();
65 let path = temp_file.path();
66
67 let result = read_n_bytes_from_file(path, 10).unwrap();
68 assert_eq!(result.as_slice(), data);
69 }
70
71 #[test]
72 fn test_read_n_bytes_from_file_less_than_requested() {
73 let mut temp_file = NamedTempFile::new().unwrap();
74 let data = b"hello world this is a test";
75 temp_file.write_all(data).unwrap();
76 let path = temp_file.path();
77
78 let result = read_n_bytes_from_file(path, 5).unwrap();
79 assert_eq!(result.as_slice(), b"hello");
80 }
81
82 #[test]
83 fn test_read_n_bytes_from_file_zero() {
84 let mut temp_file = NamedTempFile::new().unwrap();
85 let data = b"hello";
86 temp_file.write_all(data).unwrap();
87 let path = temp_file.path();
88
89 let result = read_n_bytes_from_file(path, 0).unwrap();
90 assert_eq!(result.as_slice(), b"");
91 }
92
93 #[test]
94 fn test_read_n_bytes_from_file_nonexistent() {
95 let path = std::path::Path::new("/nonexistent/file");
96 let result = read_n_bytes_from_file(path, 10);
97 assert!(result.is_err());
98 assert!(matches!(result, Err(WorkflowError::Io(_))));
100 }
101}