appcui 0.4.13

A feature-rich and cross-platform TUI/CUI framework for Rust, enabling modern terminal-based applications on Windows, Linux, and macOS. Includes built-in UI components like buttons, menus, list views, tree views, checkboxes, and more. Perfect for building fast and interactive CLI tools and text-based interfaces.
Documentation
use super::IntFormat;
use super::super::OutputBuffer;
use super::ValidateResult;

fn value_from_bytes(bytes: [u8; 8], format: IntFormat) -> i64 {
    match format {
        IntFormat::I8 => bytes[0] as i8 as i64,
        IntFormat::I16 => i16::from_ne_bytes([bytes[0], bytes[1]]) as i64,
        IntFormat::I32 => i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as i64,
        IntFormat::I64 => i64::from_ne_bytes(bytes),
    }
}

fn abs_value(value: i64) -> u64 {
    if value >= 0 {
        value as u64
    } else if value == i64::MIN {
        9223372036854775808u64
    } else {
        (-value) as u64
    }
}

pub(super) fn write(bytes: [u8; 8], format: IntFormat, output: &mut OutputBuffer) {
    let value = value_from_bytes(bytes, format);
    let width = display_chars(format) as usize;
    let sign = if value < 0 { b'-' } else { b'+' };
    let mut v = abs_value(value);
    let mut buf = [b' '; 20];
    let mut pos = width;
    if v == 0 {
        buf[width - 1] = b'0';
        pos = width - 1;
    } else {
        while v > 0 {
            pos -= 1;
            buf[pos] = (v % 10) as u8 + b'0';
            v /= 10;
        }
    }
    pos -= 1;
    buf[pos] = sign;
    for (i, val) in buf.iter().enumerate().take(width) {
        output.set(i, *val);
    }
    output.set_len(width as u8);
}
pub(super) fn validate(text: &str, _format: IntFormat) -> ValidateResult {
    let buf = text.as_bytes();
    for b in buf {
        if !matches!(*b, b'0'..=b'9' | b' ' | b'+' | b'-') {
            return ValidateResult::FormatError;
        }
    }
    ValidateResult::Valid
}
pub(super) fn convert_to_bytes(text: &str, format: IntFormat) -> ([u8; 8], u8) {
    if let Ok(n) = text.trim().parse::<i64>() {
        let bytes = n.to_ne_bytes();
        (bytes, format as u8)
    } else {
        ([0; 8], 0)
    }
}
pub(super) fn display_chars(format: IntFormat) -> u32 {
    match format {
        IntFormat::I8 => 4,
        IntFormat::I16 => 6,
        IntFormat::I32 => 11,
        IntFormat::I64 => 20,
    }
}