Skip to content

Commit

Permalink
feat: file write b64 encode
Browse files Browse the repository at this point in the history
  • Loading branch information
Furrior committed May 14, 2024
1 parent 7874b8f commit abe9702
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 2 deletions.
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@ lto = true
debug = true

[dependencies]
thiserror = "1.0.6"
translit = {version = "0.5.0", optional = true }
regex = {version = "1.10.4", optional = true }
regex-cache = {version = "0.2.1", optional = true }
base64 = {version = "0.22.1", optional = true}

byondapi = {version = "0.4.7", optional = true }
eyre = {version = "0.6.12", optional = true }

[features]
default = [
"transliteration",
"regexp"
"regexp",
"file"
]

transliteration = ["translit"]
regexp = ["regex", "regex-cache"]

file = ["base64"]
1 change: 1 addition & 0 deletions dmsrc/file.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define rustutils_file_write_b64decode(text, fname) CALL_LIB(RUST_UTILS, "file_write")(text, fname, "true")
44 changes: 44 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use std::{
io,
result,
str::Utf8Error,
};
use thiserror::Error;

pub type Result<T> = result::Result<T, Error>;

#[derive(Error, Debug)]
pub enum Error {
#[error("Illegal null character in string.")]
Null,
#[error("Invalid UTF-8 character at position {position}.")]
Utf8 { source: Utf8Error, position: usize },
#[error("Invalid or empty filename specified.")]
InvalidFilename,
#[error(transparent)]
Io(#[from] io::Error),
#[error("Invalid algorithm specified.")]
InvalidAlgorithm,
}


impl From<Utf8Error> for Error {
fn from(source: Utf8Error) -> Self {
Self::Utf8 {
source,
position: source.valid_up_to(),
}
}
}

impl From<Error> for String {
fn from(error: Error) -> Self {
error.to_string()
}
}

impl From<Error> for Vec<u8> {
fn from(error: Error) -> Self {
error.to_string().into_bytes()
}
}
40 changes: 40 additions & 0 deletions src/file.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::error::Result;
use base64::Engine;
use std::{
fs::File,
io::{BufWriter, Write},
};
byond_fn!(fn file_write(data, path, ...rest) {
let mut should_decode_b64 = false;
if rest.first().map(|x| &**x) == Some("true") {
should_decode_b64 = true;
}
write(data, path, should_decode_b64).err()
});

fn write(data: &str, path: &str, base64decode: bool) -> Result<usize> {
let path: &std::path::Path = path.as_ref();
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}

let mut file = BufWriter::new(File::create(path)?);

let written = if base64decode {
file.write(
base64::prelude::BASE64_STANDARD
.decode(data)
.unwrap()
.as_ref(),
)?
} else {
file.write(data.as_bytes())?
};

file.flush()?;
file.into_inner()
.map_err(|e| std::io::Error::new(e.error().kind(), e.error().to_string()))? // This is god-awful, but the compiler REFUSES to let me get an owned copy of `e`
.sync_all()?;

Ok(written)
}
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

#[macro_use]
mod byond;
#[allow(dead_code)]
mod error;

#[cfg(feature = "regexp")]
pub mod regexp;
#[cfg(feature = "transliteration")]
pub mod transliteration;
#[cfg(feature = "file")]
pub mod file;

#[cfg(not(target_pointer_width = "32"))]
compile_error!("rust-utils must be compiled for a 32-bit target");

0 comments on commit abe9702

Please sign in to comment.