From feefa43e65e56f6d23fa96981128841fef609414 Mon Sep 17 00:00:00 2001
From: Jason Volk <jason@zemos.net>
Date: Tue, 12 Nov 2024 22:01:32 +0000
Subject: [PATCH] add pretty/si-unit byte size parsing/printing utils

Signed-off-by: Jason Volk <jason@zemos.net>
---
 Cargo.lock              |  7 +++++++
 Cargo.toml              |  3 +++
 src/core/Cargo.toml     |  1 +
 src/core/utils/bytes.rs | 30 +++++++++++++++++++++++++++++-
 4 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/Cargo.lock b/Cargo.lock
index a1654ff96..515712644 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -458,6 +458,12 @@ version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
 
+[[package]]
+name = "bytesize"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
+
 [[package]]
 name = "bzip2-sys"
 version = "0.1.11+1.0.8"
@@ -683,6 +689,7 @@ dependencies = [
  "arrayvec",
  "axum",
  "bytes",
+ "bytesize",
  "cargo_toml",
  "checked_ops",
  "chrono",
diff --git a/Cargo.toml b/Cargo.toml
index 5ea6b4e09..0173e7cf9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -466,6 +466,9 @@ version = "1.0.36"
 [workspace.dependencies.proc-macro2]
 version = "1.0.89"
 
+[workspace.dependencies.bytesize]
+version = "1.3.0"
+
 #
 # Patches
 #
diff --git a/src/core/Cargo.toml b/src/core/Cargo.toml
index 4fe413e93..b93f9a777 100644
--- a/src/core/Cargo.toml
+++ b/src/core/Cargo.toml
@@ -57,6 +57,7 @@ argon2.workspace = true
 arrayvec.workspace = true
 axum.workspace = true
 bytes.workspace = true
+bytesize.workspace = true
 cargo_toml.workspace = true
 checked_ops.workspace = true
 chrono.workspace = true
diff --git a/src/core/utils/bytes.rs b/src/core/utils/bytes.rs
index e8975a491..441ba422a 100644
--- a/src/core/utils/bytes.rs
+++ b/src/core/utils/bytes.rs
@@ -1,4 +1,32 @@
-use crate::Result;
+use bytesize::ByteSize;
+
+use crate::{err, Result};
+
+/// Parse a human-writable size string w/ si-unit suffix into integer
+#[inline]
+pub fn from_str(str: &str) -> Result<usize> {
+	let bytes: ByteSize = str
+		.parse()
+		.map_err(|e| err!(Arithmetic("Failed to parse byte size: {e}")))?;
+
+	let bytes: usize = bytes
+		.as_u64()
+		.try_into()
+		.map_err(|e| err!(Arithmetic("Failed to convert u64 to usize: {e}")))?;
+
+	Ok(bytes)
+}
+
+/// Output a human-readable size string w/ si-unit suffix
+#[inline]
+#[must_use]
+pub fn pretty(bytes: usize) -> String {
+	const SI_UNITS: bool = true;
+
+	let bytes: u64 = bytes.try_into().expect("failed to convert usize to u64");
+
+	bytesize::to_string(bytes, SI_UNITS)
+}
 
 #[inline]
 #[must_use]
-- 
GitLab