use alloc::format;
use core::{cmp, fmt};
#[derive(Debug)]
pub struct InformantLine<'a> {
pub enable_colors: bool,
pub chain_name: &'a str,
pub relay_chain: Option<RelayChain<'a>>,
pub max_line_width: u32,
pub num_peers: u64,
pub num_network_connections: u64,
pub network_known_best: Option<u64>,
pub best_number: u64,
pub best_hash: &'a [u8],
pub finalized_number: u64,
pub finalized_hash: &'a [u8],
}
#[derive(Debug)]
pub struct RelayChain<'a> {
pub chain_name: &'a str,
pub best_number: u64,
}
impl<'a> fmt::Display for InformantLine<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let cyan = if self.enable_colors { "\x1b[36m" } else { "" };
let white_bold = if self.enable_colors { "\x1b[1;37m" } else { "" };
let light_gray = if self.enable_colors { "\x1b[90m" } else { "" };
let reset = if self.enable_colors { "\x1b[0m" } else { "" };
let (header, header_len) = if let Some(relay_chain) = &self.relay_chain {
let header = format!(
" {cyan}{chain_name}{reset} {white_bold}{local_best:<10}{reset} {light_gray}({relay_chain_name} {relay_best}){reset} [",
cyan = cyan,
reset = reset,
white_bold = white_bold,
light_gray = light_gray,
chain_name = self.chain_name,
relay_chain_name = relay_chain.chain_name,
local_best = BlockNumberDisplay(self.best_number),
relay_best = BlockNumberDisplay(relay_chain.best_number),
);
let header_len = self.chain_name.chars().count() + relay_chain.chain_name.len() + 29; (header, header_len)
} else {
let header = format!(
" {cyan}{chain_name}{reset} {white_bold}{local_best:<10}{reset} [",
cyan = cyan,
reset = reset,
white_bold = white_bold,
chain_name = self.chain_name,
local_best = BlockNumberDisplay(self.best_number),
);
let header_len = self.chain_name.chars().count() + 19; (header, header_len)
};
let trailer = format!(
"] {white_bold}{network_best}{reset} (🔗{white_bold}{peers:>3}{reset}) (🌐{white_bold}{connec:>4}{reset}) ",
network_best = self
.network_known_best
.map(BlockNumberDisplay)
.map_or(either::Right("?"), either::Left),
peers = self.num_network_connections,
connec = self.num_network_connections,
white_bold = white_bold,
reset = reset,
);
let trailer_len = format!(
"] {network_best} ( {peers:>3}) ( {connec:>4}) ",
network_best = self
.network_known_best
.map(BlockNumberDisplay)
.map(either::Left)
.unwrap_or(either::Right("?")),
peers = self.num_network_connections,
connec = self.num_network_connections,
)
.len();
let bar_width = self
.max_line_width
.saturating_sub(u32::try_from(header_len).unwrap())
.saturating_sub(u32::try_from(trailer_len).unwrap());
let actual_network_best = cmp::max(self.network_known_best.unwrap_or(0), self.best_number);
assert!(self.best_number <= actual_network_best);
let bar_done_width = u128::from(self.best_number)
.checked_mul(u128::from(bar_width))
.unwrap()
.checked_div(u128::from(actual_network_best))
.unwrap_or(0); let bar_done_width = u32::try_from(bar_done_width).unwrap();
let done_bar1 = "=".repeat(usize::try_from(bar_done_width.saturating_sub(1)).unwrap());
let done_bar2 = if bar_done_width == bar_width {
'='
} else {
'>'
};
let todo_bar = " ".repeat(
usize::try_from(
bar_width
.checked_sub(bar_done_width.saturating_sub(1).saturating_add(1))
.unwrap(),
)
.unwrap(),
);
assert_eq!(
done_bar1.len() + 1 + todo_bar.len(),
usize::try_from(bar_width).unwrap()
);
write!(f, "{header}{done_bar1}{done_bar2}{todo_bar}{trailer}")
}
}
pub struct HashDisplay<'a>(pub &'a [u8]);
impl<'a> fmt::Display for HashDisplay<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "0x")?;
if self.0.len() >= 2 {
let val = u16::from_be_bytes(<[u8; 2]>::try_from(&self.0[..2]).unwrap());
write!(f, "{val:04x}")?;
}
if self.0.len() >= 5 {
write!(f, "…")?;
}
if self.0.len() >= 4 {
let len = self.0.len();
let val = u16::from_be_bytes(<[u8; 2]>::try_from(&self.0[len - 2..]).unwrap());
write!(f, "{val:04x}")?;
}
Ok(())
}
}
pub struct BytesDisplay(pub u64);
impl fmt::Display for BytesDisplay {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut value = self.0 as f64;
if value < 1000.0 {
return write!(f, "{value} B");
}
value /= 1024.0;
if value < 100.0 {
return write!(f, "{value:.1} kiB");
}
if value < 1000.0 {
return write!(f, "{value:.0} kiB");
}
value /= 1024.0;
if value < 100.0 {
return write!(f, "{value:.1} MiB");
}
if value < 1000.0 {
return write!(f, "{value:.0} MiB");
}
value /= 1024.0;
if value < 100.0 {
return write!(f, "{value:.1} GiB");
}
if value < 1000.0 {
return write!(f, "{value:.0} GiB");
}
value /= 1024.0;
if value < 100.0 {
return write!(f, "{value:.1} TiB");
}
if value < 1000.0 {
return write!(f, "{value:.0} TiB");
}
value /= 1024.0;
write!(f, "{value:.1} PiB")
}
}
struct BlockNumberDisplay(u64);
impl fmt::Display for BlockNumberDisplay {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "#{}", self.0)?;
Ok(())
}
}