-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfiles.rs
More file actions
59 lines (48 loc) · 1.58 KB
/
Copy pathfiles.rs
File metadata and controls
59 lines (48 loc) · 1.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use std::fs::{self, File};
use std::io::{Error, ErrorKind, Read, Write};
use std::path::{Component, Path, PathBuf};
pub type FileResult<T> = Result<T, FileError>;
pub enum FileError {
InvalidPath,
NotFound,
PermissionDenied,
Io(Error),
}
fn map_io_error(err: Error) -> FileError {
match err.kind() {
ErrorKind::NotFound => FileError::NotFound,
ErrorKind::PermissionDenied => FileError::PermissionDenied,
_ => FileError::Io(err),
}
}
fn validate_file_name(file_name: &str) -> FileResult<()> {
let path = Path::new(file_name);
if path
.components()
.any(|c| !matches!(c, Component::Normal(_)))
{
return Err(FileError::InvalidPath);
}
Ok(())
}
fn resolve_path(path: &Path, file_name: &str) -> FileResult<PathBuf> {
validate_file_name(file_name)?;
let canonical_path = fs::canonicalize(path).map_err(map_io_error)?;
Ok(canonical_path.join(file_name))
}
pub struct FileManager;
impl FileManager {
pub fn create(path: &Path, file_name: &str, body: &[u8]) -> FileResult<()> {
let full_path = resolve_path(path, file_name)?;
let mut f = File::create(&full_path).map_err(map_io_error)?;
f.write_all(body).map_err(map_io_error)?;
Ok(())
}
pub fn read(path: &Path, file_name: &str) -> FileResult<Vec<u8>> {
let full_path = resolve_path(path, file_name)?;
let mut file = File::open(full_path).map_err(map_io_error)?;
let mut contents: Vec<u8> = Vec::new();
file.read_to_end(&mut contents).map_err(map_io_error)?;
Ok(contents)
}
}