rowid 0.5.0

A time-based unique ID solution
Documentation
use std::{collections::HashMap, io, time::SystemTime};

use crate::{
    common::{configs::TIMESTAMP_LENGTH, errors::RowIDError},
    time::timestamp_to_system_time,
};

pub struct DecodeOptions<CharList: AsRef<str>, Encoded: AsRef<str>> {
    pub char_list: CharList,
    pub encoded: Encoded,
}

pub fn _decode<CharList: AsRef<str>, Encoded: AsRef<str>>(
    opts: DecodeOptions<CharList, Encoded>
) -> io::Result<SystemTime> {
    let char_list: &str = opts.char_list.as_ref();
    let encoded: &str = opts.encoded.as_ref();

    if encoded.len() < TIMESTAMP_LENGTH {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            RowIDError::EncodedLength.as_str(),
        ));
    }

    let char_list: Vec<char> = char_list.chars().collect();
    let char_list_length: usize = char_list.len();
    let char_index_map: HashMap<char, usize> =
        char_list.iter().enumerate().map(|(i, &c)| (c, i)).collect();

    let mut encoded_chars: [char; TIMESTAMP_LENGTH] = ['\0'; TIMESTAMP_LENGTH];

    for (i, c) in encoded[..TIMESTAMP_LENGTH].chars().enumerate() {
        encoded_chars[i] = c;
    }

    if !encoded_chars.iter().all(|c| char_index_map.contains_key(c)) {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            RowIDError::InvalidEncoded.as_str(),
        ));
    }

    let mut timestamp: usize = 0;

    for c in encoded_chars {
        if let Some(index) = char_index_map.get(&c) {
            timestamp = timestamp * char_list_length + index;
        } else {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                RowIDError::InvalidEncoded.as_str(),
            ));
        }
    }

    Ok(timestamp_to_system_time(timestamp))
}