/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2025 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
use colored::Colorize;
use std::time::{SystemTime, UNIX_EPOCH};
mod clip;
pub use clip::Clipboard;
pub fn is_whitespace(s: &str) -> bool {
s.chars().all(char::is_whitespace)
}
pub fn min_f32(x: f32, y: f32) -> f32 {
if x < y {
x
} else {
y
}
}
/// Use src/util/time.rs Timestamp instead of this.
pub fn unixtime() -> u64 {
let timest = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis();
assert!(timest < std::u64::MAX as u128);
timest as u64
}
#[allow(dead_code)]
pub fn ansi_texture(width: usize, height: usize, data: &Vec) -> String {
let mut out = String::new();
out.push('┌');
for _ in 0..width {
out.push('─');
}
out.push('┐');
out.push('\n');
for i in 0..height {
out.push('│');
for j in 0..width {
let idx = 4 * (i * width + j);
let r = data[idx];
let g = data[idx + 1];
let b = data[idx + 2];
let a = data[idx + 3];
#[cfg(target_os = "android")]
{
if a > 204 {
out.push('█');
} else if a > 153 {
out.push('▓');
} else if a > 102 {
out.push('▒');
} else if a > 51 {
out.push('░');
} else {
out.push(' ');
}
}
#[cfg(target_os = "linux")]
{
let r = ((a as f32 * r as f32) / 255.) as u8;
let g = ((a as f32 * g as f32) / 255.) as u8;
let b = ((a as f32 * b as f32) / 255.) as u8;
let val = "█".truecolor(r, g, b).to_string();
out.push_str(&val);
}
}
out.push('│');
out.push('\n');
}
out.push('└');
for _ in 0..width {
out.push('─');
}
out.push('┘');
out.push('\n');
out
}
pub struct TupleIterStruct3 {
idx: usize,
i1: I1,
i2: I2,
i3: I3,
}
impl Iterator for TupleIterStruct3
where
I1: Iterator,
I2: Iterator,
I3: Iterator,
{
type Item = (usize, I1::Item, I2::Item, I3::Item);
fn next(&mut self) -> Option {
let Some(x1) = self.i1.next() else { return None };
let Some(x2) = self.i2.next() else { return None };
let Some(x3) = self.i3.next() else { return None };
let res = (self.idx, x1, x2, x3);
self.idx += 1;
Some(res)
}
}
pub fn zip3(i1: I1, i2: I2, i3: I3) -> TupleIterStruct3
where
I1: Iterator- ,
I2: Iterator
- ,
I3: Iterator
- ,
{
TupleIterStruct3 { idx: 0, i1, i2, i3 }
}
pub struct TupleIterStruct4 {
idx: usize,
i1: I1,
i2: I2,
i3: I3,
i4: I4,
}
impl Iterator for TupleIterStruct4
where
I1: Iterator,
I2: Iterator,
I3: Iterator,
I4: Iterator,
{
type Item = (usize, I1::Item, I2::Item, I3::Item, I4::Item);
fn next(&mut self) -> Option {
let Some(x1) = self.i1.next() else { return None };
let Some(x2) = self.i2.next() else { return None };
let Some(x3) = self.i3.next() else { return None };
let Some(x4) = self.i4.next() else { return None };
let res = (self.idx, x1, x2, x3, x4);
self.idx += 1;
Some(res)
}
}
#[allow(dead_code)]
pub fn zip4(
i1: I1,
i2: I2,
i3: I3,
i4: I4,
) -> TupleIterStruct4
where
I1: Iterator
- ,
I2: Iterator
- ,
I3: Iterator
- ,
I4: Iterator
- ,
{
TupleIterStruct4 { idx: 0, i1, i2, i3, i4 }
}
pub fn enumerate(v: Vec) -> impl Iterator
- {
v.into_iter().enumerate()
}
pub fn enumerate_ref(v: &Vec) -> impl Iterator
- {
v.iter().enumerate()
}
pub fn enumerate_mut(v: &mut Vec) -> impl Iterator
- {
v.iter_mut().enumerate()
}