Skip to content

Commit

Permalink
[Enhancement] Truncate PathBuf-like Objects (#68)
Browse files Browse the repository at this point in the history
* Added ::= src/writing.rs

* Added ::= PathBufLikeTruncation::truncate_loudly

* Added ::= PathBufLikeTruncation::truncate_silently

* Added ::= tests/writing.rs

* Added ::= PathBufLikeTruncation

* Create summary of recent changes

* Skip ::= fix typo

---------

Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
kevinmatthes and github-actions[bot] committed Jan 25, 2024
1 parent adaebeb commit badc251
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(
references: {},
changes: {
"Added": [
"PathBufLikeTruncation",
"PathBufLikeTruncation::truncate_loudly",
"PathBufLikeTruncation::truncate_silently",
"src/writing.rs",
"tests/writing.rs",
],
},
)
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@
)]

mod reading;
mod writing;

pub use reading::{BufReadReader, OptionReader, PathBufLikeReader};
pub use writing::PathBufLikeTruncation;

/// This crate's name.
pub const NAME: &str = "aeruginous-io";
Expand Down
123 changes: 123 additions & 0 deletions src/writing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*********************** GNU General Public License 3.0 ***********************\
| |
| Copyright (C) 2024 Kevin Matthes |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <https://www.gnu.org/licenses/>. |
| |
\******************************************************************************/

use std::{io::Write, path::PathBuf};
use sysexits::Result;

/// Truncate files given as instances convertible to a [`std::path::PathBuf`].
pub trait PathBufLikeTruncation<T>
where
PathBuf: From<T>,
{
/// Truncate the given file using the data this method is called on.
///
/// This method behaves just like
/// [`crate::PathBufLikeTruncation::truncate_silently`] despite also
/// printing error messages to [`std::io::Stderr`].
///
/// # Errors
///
/// See [`sysexits::ExitCode`].
fn truncate_loudly(self, destination: T) -> Result<()>;

/// Truncate the given file using the data this method is called on.
///
/// The data this method is called on will be converted to a [`String`] and
/// written to the given file. The data therefore needs to implement
/// [`ToString`]. The file needs to be convertible to a
/// [`std::path::PathBuf`]. The file will be truncated.
///
/// The return value is either the unit type, in case of success, or a
/// [`sysexits::ExitCode`] to describe the error cause, otherwise.
///
/// Error messages are not written to [`std::io::Stderr`].
///
/// # Errors
///
/// See [`sysexits::ExitCode`].
fn truncate_silently(self, destination: T) -> Result<()>;
}

impl<P, T: ToString> PathBufLikeTruncation<P> for T
where
PathBuf: From<P>,
{
fn truncate_loudly(self, destination: P) -> Result<()> {
match std::fs::File::options()
.append(false)
.create(true)
.truncate(true)
.write(true)
.open(PathBuf::from(destination))
{
Err(e) => {
eprintln!("{e}");
Err(e.into())
}
Ok(mut file) => {
let bytes = self.to_string().as_bytes().to_vec();

match file.write(&bytes) {
Err(e) => {
eprintln!("{e}");
Err(e.into())
}
Ok(n) => {
if n == bytes.len() {
Ok(())
} else {
eprintln!(
"Creating an exact copy was not possible."
);
Err(sysexits::ExitCode::IoErr)
}
}
}
}
}
}

fn truncate_silently(self, destination: P) -> Result<()> {
match std::fs::File::options()
.append(false)
.create(true)
.truncate(true)
.write(true)
.open(PathBuf::from(destination))
{
Err(e) => Err(e.into()),
Ok(mut file) => {
let bytes = self.to_string().as_bytes().to_vec();

match file.write(&bytes) {
Err(e) => Err(e.into()),
Ok(n) => {
if n == bytes.len() {
Ok(())
} else {
Err(sysexits::ExitCode::IoErr)
}
}
}
}
}
}
}

/******************************************************************************/
54 changes: 54 additions & 0 deletions tests/writing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*********************** GNU General Public License 3.0 ***********************\
| |
| Copyright (C) 2024 Kevin Matthes |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <https://www.gnu.org/licenses/>. |
| |
\******************************************************************************/

mod path_buf_like_truncation {
use aeruginous_io::{PathBufLikeReader, PathBufLikeTruncation};

#[test]
fn truncate_loudly_failure() {
assert!(String::new().truncate_loudly("tests/").is_err());
}

#[test]
fn truncate_loudly_success() {
let f = "path_buf_like_truncation_truncate_loudly_success.txt";

assert!("test\n".truncate_loudly(f).is_ok());
assert_eq!(f.read_silently().unwrap(), "test\n");

std::fs::remove_file(f).unwrap();
}

#[test]
fn truncate_silently_failure() {
assert!(String::new().truncate_silently("tests/").is_err());
}

#[test]
fn truncate_silently_success() {
let f = "path_buf_like_truncation_truncate_silently_success.txt";

assert!("test\n".truncate_silently(f).is_ok());
assert_eq!(f.read_silently().unwrap(), "test\n");

std::fs::remove_file(f).unwrap();
}
}

/******************************************************************************/

0 comments on commit badc251

Please sign in to comment.