const_format/
__ascii_case_conv.rsmod word_iterator;
use word_iterator::WordIterator;
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Case {
    Lower,
    Upper,
    Pascal,
    Camel,
    Snake,
    UpperSnake,
    Kebab,
    UpperKebab,
}
macro_rules! if_next_word {
    ($word_iterator:ident, $word_range:ident => $then:block $(else $else:block)? ) => {
        #[allow(unused_mut)]
        if let Some((niter, mut $word_range)) = $word_iterator.next() {
            $word_iterator = niter;
            $then
        } $(else $else)?
    };
}
macro_rules! while_next_word {
    ($word_iterator:ident, $word_range:ident => $then:block) => {
        #[allow(unused_mut)]
        while let Some((niter, mut $word_range)) = $word_iterator.next() {
            $word_iterator = niter;
            $then
        }
    };
}
struct WordCountAndLength {
    count: usize,
    length: usize,
}
const fn words_count_and_length(bytes: &[u8]) -> WordCountAndLength {
    let mut count = 0;
    let mut length = 0;
    let mut word_iter = WordIterator::new(bytes);
    while_next_word! {word_iter, word_range => {
        count += 1;
        length += word_range.end - word_range.start;
    }}
    WordCountAndLength { count, length }
}
pub const fn size_after_conversion(case: Case, s: &str) -> usize {
    match case {
        Case::Upper | Case::Lower => s.len(),
        Case::Pascal | Case::Camel => {
            let wcl = words_count_and_length(s.as_bytes());
            wcl.length
        }
        Case::Snake | Case::Kebab | Case::UpperSnake | Case::UpperKebab => {
            let wcl = words_count_and_length(s.as_bytes());
            wcl.length + wcl.count.saturating_sub(1)
        }
    }
}
pub const fn convert_str<const N: usize>(case: Case, s: &str) -> [u8; N] {
    let mut arr = [0; N];
    let mut inp = s.as_bytes();
    let mut o = 0;
    macro_rules! map_bytes {
        ($byte:ident => $e:expr) => {
            while let [$byte, rem @ ..] = inp {
                let $byte = *$byte;
                inp = rem;
                arr[o] = $e;
                o += 1;
            }
        };
    }
    macro_rules! write_byte {
        ($byte:expr) => {
            arr[o] = $byte;
            o += 1;
        };
    }
    macro_rules! write_range_from {
        ($range:expr, $from:expr, $byte:ident => $mapper:expr) => {{
            let mut range = $range;
            while range.start < range.end {
                let $byte = $from[range.start];
                arr[o] = $mapper;
                range.start += 1;
                o += 1;
            }
        }};
    }
    macro_rules! write_snake_kebab_case {
        ($separator:expr, $byte_conversion:expr) => {{
            let mut word_iter = WordIterator::new(inp);
            if_next_word! {word_iter, word_range => {
                write_range_from!(word_range, inp, byte => $byte_conversion(byte));
                while_next_word!{word_iter, word_range => {
                    write_byte!($separator);
                    write_range_from!(word_range, inp, byte => $byte_conversion(byte));
                }}
            }}
        }};
    }
    macro_rules! write_pascal_camel_case {
        ($first_word_conv:expr) => {{
            let mut word_iter = WordIterator::new(inp);
            if_next_word! {word_iter, word_range => {
                write_byte!($first_word_conv(inp[word_range.start]));
                word_range.start += 1;
                write_range_from!(word_range, inp, byte => lowercase_u8(byte));
                while_next_word!{word_iter, word_range => {
                    write_byte!(uppercase_u8(inp[word_range.start]));
                    word_range.start += 1;
                    write_range_from!(word_range, inp, byte => lowercase_u8(byte));
                }}
            }}
        }};
    }
    match case {
        Case::Upper => map_bytes!(b => uppercase_u8(b)),
        Case::Lower => map_bytes!(b => lowercase_u8(b)),
        Case::Snake => write_snake_kebab_case!(b'_', lowercase_u8),
        Case::UpperSnake => write_snake_kebab_case!(b'_', uppercase_u8),
        Case::Kebab => write_snake_kebab_case!(b'-', lowercase_u8),
        Case::UpperKebab => write_snake_kebab_case!(b'-', uppercase_u8),
        Case::Pascal => write_pascal_camel_case!(uppercase_u8),
        Case::Camel => write_pascal_camel_case!(lowercase_u8),
    }
    arr
}
const CASE_DIFF: u8 = b'a' - b'A';
const fn uppercase_u8(b: u8) -> u8 {
    if let b'a'..=b'z' = b {
        b - CASE_DIFF
    } else {
        b
    }
}
const fn lowercase_u8(b: u8) -> u8 {
    if let b'A'..=b'Z' = b {
        b + CASE_DIFF
    } else {
        b
    }
}