- add read_file_bytes
- rename read_file_to_str() -> read_file_str()
- change return types of read_file_* to Result<T, std::io::Error>
- unpub shell::run()
- don't overwrite $PATH in shell::run()
- remove unnecessary tests

Signed-off-by: Ivan Bushchik <ivabus@ivabus.dev>
This commit is contained in:
Ivan Bushchik 2023-09-14 18:39:44 +03:00
parent f96e9b8be6
commit 8449b97658
No known key found for this signature in database
GPG key ID: 2F16FBF3262E090C
4 changed files with 36 additions and 56 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "smurf" name = "smurf"
version = "0.2.0" version = "0.3.0"
edition = "2021" edition = "2021"
authors = ["Ivan Bushchik <ivabus@ivabus.dev>"] authors = ["Ivan Bushchik <ivabus@ivabus.dev>"]
description = "SMall Useful Rust Functions" description = "SMall Useful Rust Functions"

View file

@ -7,18 +7,20 @@
### IO ### IO
- macros input!(T) and input_vec!(T), that could be used to simplify stdin process - macros input!(T) and input_vec!(T), that could be used to simplify stdin process
- read_file_to_str() basically reads file to string (yes.) - read_file_str() basically reads file to string (yes.)
- read_file_bytes() see read_file_str()
### Shell ### Shell
- macros shell!() - macros shell!()
## Usage ## Usage
Add this to your `Cargo.toml`: Add this to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
smurf = "0.2" smurf = "0.3"
``` ```
and this to your crate root: and this to your crate root:
@ -49,4 +51,4 @@ fn main() {
## License ## License
[MIT](LICENSE-MIT) [MIT](./LICENSE)

View file

@ -1,40 +1,36 @@
use std::fs::File; use std::fs::File;
use std::io::{prelude::*, BufReader}; use std::io::{prelude::*, BufReader};
pub fn read_file_to_str(path: &std::path::PathBuf) -> Option<String> { pub fn read_file_str(path: &std::path::PathBuf) -> Result<String, std::io::Error> {
let file = File::open(&path); let file = File::open(&path)?;
let file = match file {
Ok(data) => data,
Err(_) => {
eprintln!("Cannot open file \"{}\"", path.display());
return None
}
};
let mut buf_reader = BufReader::new(file); let mut buf_reader = BufReader::new(file);
let mut content = String::new(); let mut content = String::new();
buf_reader.read_to_string(&mut content).unwrap(); buf_reader.read_to_string(&mut content)?;
Some(content) Ok(content)
} }
pub fn read_file_bytes(path: &std::path::PathBuf) -> Result<Vec<u8>, std::io::Error> {
let file = File::open(&path)?;
let mut buf_reader = BufReader::new(file);
let mut content: Vec<u8> = Vec::new();
buf_reader.read_to_end(&mut content)?;
Ok(content)
}
#[macro_export] #[macro_export]
macro_rules! input { macro_rules! input {
($t:ty) => { ($t:ty) => {{
{ let mut input = String::new();
let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap();
std::io::stdin().read_line(&mut input).unwrap(); input.trim().parse::<$t>().unwrap()
input.trim().parse::<$t>().unwrap() }};
}
}
} }
#[macro_export] #[macro_export]
macro_rules! input_vec { macro_rules! input_vec {
($t:ty) => { ($t:ty) => {{
{ let mut input = String::new();
let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap();
std::io::stdin().read_line(&mut input).unwrap(); input.trim().split_whitespace().map(|x| x.parse::<$t>().unwrap()).collect::<Vec<$t>>()
input.trim().split_whitespace().map(|x| x.parse::<$t>().unwrap()).collect::<Vec<$t>>() }};
}
}
} }

View file

@ -13,7 +13,8 @@ pub struct ShellResult {
pub stderr: String, pub stderr: String,
} }
pub fn run(command: String) -> ShellResult { #[allow(dead_code)]
fn run(command: String) -> ShellResult {
let mut iter = command.split_whitespace(); let mut iter = command.split_whitespace();
let mut current = iter.next(); let mut current = iter.next();
let mut words: Vec<&str> = vec![]; let mut words: Vec<&str> = vec![];
@ -23,7 +24,6 @@ pub fn run(command: String) -> ShellResult {
} }
let command = Command::new(&words[0]) let command = Command::new(&words[0])
.args(&words[1..]) .args(&words[1..])
.env("PATH", "/bin:/usr/bin") // TODO: Make this configurable
.output() .output()
.expect(&format!("Failed to execute '{}'", command)); .expect(&format!("Failed to execute '{}'", command));
return ShellResult { return ShellResult {
@ -35,6 +35,9 @@ pub fn run(command: String) -> ShellResult {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
// Testing basic usage and only on unix
#[cfg(unix)]
#[test] #[test]
fn test_shell_macro() { fn test_shell_macro() {
let result = shell!("echo hello"); let result = shell!("echo hello");
@ -43,17 +46,7 @@ mod tests {
assert_eq!(result.stderr, ""); assert_eq!(result.stderr, "");
} }
/* You literally can't use pipe using std::process::Command */ #[cfg(unix)]
// TODO: figure out how to test this
#[ignore]
#[test]
fn test_shell_macro_with_stderr() {
let result = shell!("echo hello 1>&2");
assert_eq!(result.code, 0);
assert_eq!(result.stdout, "");
assert_eq!(result.stderr, "hello\n");
}
#[test] #[test]
fn test_shell_macro_with_args() { fn test_shell_macro_with_args() {
let result = shell!("echo {} {}", "hello", "world"); let result = shell!("echo {} {}", "hello", "world");
@ -61,15 +54,4 @@ mod tests {
assert_eq!(result.stdout, "hello world\n"); assert_eq!(result.stdout, "hello world\n");
assert_eq!(result.stderr, ""); assert_eq!(result.stderr, "");
} }
// TODO: figure out how to test this
#[ignore]
#[test]
fn test_shell_macro_with_code() {
let result = shell!("sh -c exit 1");
assert_eq!(result.code, 1);
assert_eq!(result.stdout, "");
assert_eq!(result.stderr, "");
}
} }