use std::fmt::Write as _;
use arboard::Clipboard;
use ratatui::layout::{Constraint, Layout, Rect};
use crate::render_order_enum;
type CommandBarArea = Rect;
type PaneAreas = [Rect; 4];
#[derive(Debug)]
pub struct ValueWithStringRepresentation<T> {
value: T,
string_representation: String,
}
impl<T: ToString> ValueWithStringRepresentation<T> {
pub fn new(value: T) -> Self {
let s = value.to_string();
ValueWithStringRepresentation {
value,
string_representation: s,
}
}
}
impl<T> std::ops::Deref for ValueWithStringRepresentation<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T> AsRef<str> for ValueWithStringRepresentation<T> {
fn as_ref(&self) -> &str {
&self.string_representation
}
}
render_order_enum!(Unit, Bytes, Kilobytes, Megabytes, Gigabytes);
impl Unit {
const KILOBYTE: u64 = 1000;
const MEGABYTE: u64 = Self::KILOBYTE * 1000;
const GIGABYTE: u64 = Self::MEGABYTE * 1000;
pub fn human_readable(&self) -> &'static str {
match self {
Unit::Bytes => "B",
Unit::Kilobytes => "kB",
Unit::Megabytes => "MB",
Unit::Gigabytes => "GB",
}
}
pub fn scale_to_units(&self, value: u64) -> u64 {
match self {
Unit::Bytes => value,
Unit::Kilobytes => value * Self::KILOBYTE,
Unit::Megabytes => value * Self::MEGABYTE,
Unit::Gigabytes => value * Self::GIGABYTE,
}
}
pub fn bytes_to_human_readable_units(bytes: impl Into<u64>) -> (f64, Self) {
let bytes = bytes.into();
match bytes {
0..Self::KILOBYTE => (bytes as f64, Self::Bytes),
Self::KILOBYTE..Self::MEGABYTE => {
((bytes as f64) / (Self::KILOBYTE as f64), Self::Kilobytes)
}
Self::MEGABYTE..Self::GIGABYTE => {
((bytes as f64) / (Self::MEGABYTE as f64), Self::Megabytes)
}
Self::GIGABYTE.. => {
((bytes as f64) / (Self::GIGABYTE as f64), Self::Gigabytes)
}
}
}
}
pub(crate) fn encode_hex(digest: impl AsRef<[u8]>) -> String {
let mut s = String::with_capacity(digest.as_ref().len() * 2);
for &b in digest.as_ref().iter() {
write!(&mut s, "{b:02x}").unwrap();
}
s
}
pub(crate) fn copy_to_clipboard(
clipboard: Option<&mut Clipboard>,
data: std::borrow::Cow<'_, str>,
) {
if let Some(clipboard) = clipboard
&& let Err(e) = clipboard.set_text(data)
{
tracing::debug!("Failed to copy text to the clipboard: {}", e);
}
}
pub(crate) fn split_layout(initial_area: Rect) -> (PaneAreas, CommandBarArea) {
let [main, command_bar] =
Layout::vertical([Constraint::Percentage(100), Constraint::Min(1)])
.areas(initial_area);
let [left, right] = Layout::horizontal([
Constraint::Percentage(35),
Constraint::Percentage(70),
])
.areas(main);
let [upper_left, middle_left, lower_left] = Layout::vertical([
Constraint::Min(8),
Constraint::Min(10),
Constraint::Percentage(100),
])
.areas(left);
([upper_left, middle_left, lower_left, right], command_bar)
}