uuinfo 0.6.0

A tool to debug unique identifiers (UUID, ULID, Snowflake, etc).
use std::fmt::Write;
use ulid::Ulid;
use uuid::Uuid;

use crate::schema::{Args, IDInfo};
use crate::utils::milliseconds_to_seconds_and_iso8601;

const PREFIX_ALPHABET: &str = "abcdefghijklmnopqrstuvwxyz_";

pub fn parse_typeid(args: &Args) -> Option<IDInfo> {
    let parts: &Vec<&str> = &args.id.split('_').collect();
    let prefix: String;
    let value: &str;
    match parts.split_last() {
        Some((last, elements)) => {
            prefix = elements.join("_");
            value = last;
        }
        None => return None,
    }
    if prefix.chars().count() > 63 || !prefix.chars().all(|c| PREFIX_ALPHABET.contains(c)) {
        return None;
    }
    let ulid = Ulid::from_string(value).ok()?;
    let uuid: Uuid = Uuid::from_bytes(ulid.to_bytes());
    let (timestamp, datetime) = milliseconds_to_seconds_and_iso8601(ulid.timestamp_ms(), None);

    Some(IDInfo {
        id_type: "TypeID".to_string(),
        standard: args.id.to_string(),
        integer: Some(ulid.0),
        uuid_wrap: Some(uuid.to_string()),
        parsed: Some("from base32, suffix only".to_string()),
        size: 128,
        entropy: 74,
        datetime: Some(datetime),
        timestamp: Some(timestamp.to_string()),
        node1: Some(prefix),
        hex: Some(hex::encode(uuid.as_bytes())),
        bits: Some(uuid.as_bytes().iter().fold(String::new(), |mut output, c| {
            let _ = write!(output, "{c:08b}");
            output
        })),
        color_map: Some("33333333333333333333333333333333333333333333333311112222222222220022222222222222222222222222222222222222222222222222222222222222".to_string()),
        ..Default::default()
    })
}