161 lines
4.2 KiB
Rust
161 lines
4.2 KiB
Rust
//! Handles conversion one letter at a time for any base
|
|
// based off this SO answer: https://stackoverflow.com/a/1119769
|
|
/// Converts a [`u32`] to catspeak
|
|
///
|
|
/// ```
|
|
/// use cat2text::core::{num_to_cat, char_length};
|
|
/// use cat2text::base4::alphabet;
|
|
///
|
|
/// assert_eq!("meow mreow mrrp".to_string(), num_to_cat(9, alphabet(), char_length(4)));
|
|
/// ```
|
|
pub fn num_to_cat(num: u32, alphabet: Vec<String>, char_length: u32) -> String {
|
|
let mut num: u32 = num.clone();
|
|
let base: u32 = alphabet.len() as u32;
|
|
|
|
// base*n*-ifying logic
|
|
let mut nums: Vec<u32> = Vec::new();
|
|
while (nums.len() as u32) < char_length {
|
|
nums.push((num as u32) % base);
|
|
num /= base;
|
|
}
|
|
nums.reverse();
|
|
|
|
let mut result: Vec<String> = Vec::new();
|
|
for item in nums {
|
|
result.push(alphabet[item as usize].clone());
|
|
}
|
|
|
|
return result.join(" ");
|
|
}
|
|
|
|
/// Converts catspeak to a [`u32`]
|
|
///
|
|
/// ```
|
|
/// use cat2text::core::{cat_to_num, bytes::char_length};
|
|
/// use cat2text::base4::alphabet;
|
|
///
|
|
/// let text = vec!["meow".to_string(), "mrrp".to_string(), "mrow".to_string(), "meow".to_string()];
|
|
///
|
|
/// assert_eq!(28, cat_to_num(text, alphabet(), char_length(4)));
|
|
/// ```
|
|
pub fn cat_to_num(text: Vec<String>, alphabet: Vec<String>, char_length: u32) -> u32 {
|
|
let mut nums: Vec<u32> = Vec::new();
|
|
for word in text {
|
|
for i in 0..alphabet.len() {
|
|
if word == alphabet[i] {
|
|
nums.push(i as u32);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
let base = alphabet.len();
|
|
let mut num = 0 as u32;
|
|
for n in 0..nums.len() {
|
|
let power = (char_length - (n as u32 + 1)) as u32;
|
|
num += nums[n] * (base as u32).pow(power);
|
|
}
|
|
return num;
|
|
}
|
|
|
|
/// Splits a word encoded in catspeak every *x* segments
|
|
///
|
|
/// Used for decoding by splitting words apart into letters which can then be decoded individually
|
|
///
|
|
/// ```ignore
|
|
/// use cat2text::core::split_every_x;
|
|
///
|
|
/// assert_eq!(vec!["meow meow mrrp".to_string(), "meow mreow mrrp".to_string()], split_every_x("meow meow mrrp meow mreow mrrp".to_string(), 3));
|
|
/// ```
|
|
pub(crate) fn split_every_x(text: impl AsRef<str>, x: u32) -> Vec<String> {
|
|
let x = x as usize;
|
|
let delim = " ";
|
|
let tmp: Vec<String> = text
|
|
.as_ref()
|
|
.split(delim)
|
|
.map(|item| item.to_string())
|
|
.collect();
|
|
let mut output: Vec<String> = Vec::new();
|
|
for i in 0..tmp.len() {
|
|
if i % x == 0 {
|
|
output.push(String::new())
|
|
}
|
|
output[i / x] += tmp[i].as_str();
|
|
output[i / x] += " ";
|
|
}
|
|
|
|
// trim everything before sending it back
|
|
output = output
|
|
.into_iter()
|
|
.map(|item| item.trim().to_string())
|
|
.collect();
|
|
return output;
|
|
}
|
|
|
|
/// Returns all cat sounds in the catspeak alphabet
|
|
///
|
|
/// ```
|
|
/// use cat2text::core::alphabet;
|
|
///
|
|
/// println!("{:?}", alphabet());
|
|
/// ```
|
|
pub fn alphabet() -> Vec<String> {
|
|
return vec![
|
|
"meow", "mrrp", "mreow", "mrow", "nya~", "nyaaaa~", "mraow", "mew", "prrp", "mewo",
|
|
"purrrr", "nya", "miao", "miau", "miauw", "mrow~",
|
|
]
|
|
.into_iter()
|
|
.map(|a| a.to_string())
|
|
.collect();
|
|
}
|
|
|
|
/// Returns the max base that can be used
|
|
///
|
|
/// For example, if the available alphabet was `["meow", "mrrp", "mreow", "mrow"]`, the max base would be 4
|
|
///
|
|
/// ```
|
|
/// use cat2text::core::max_base;
|
|
///
|
|
/// println!("{}", max_base());
|
|
/// ```
|
|
pub fn max_base() -> u32 {
|
|
return alphabet().len() as u32;
|
|
}
|
|
|
|
/// Returns the minimum catspeak words per character needed for this base
|
|
///
|
|
/// ```
|
|
/// use cat2text::core::char_length;
|
|
///
|
|
/// let base = 10;
|
|
/// assert_eq!(char_length(base), 2)
|
|
/// ```
|
|
pub fn char_length(base: u32) -> u32 {
|
|
for i in 1..base + 1 {
|
|
let num = base.pow(i);
|
|
if num > 26 {
|
|
return i;
|
|
}
|
|
}
|
|
return u32::MAX;
|
|
}
|
|
|
|
pub mod bytes {
|
|
/// Returns the minimum catspeak words per character needed for this base for bytes
|
|
///
|
|
/// ```
|
|
/// use cat2text::core::bytes::char_length;
|
|
///
|
|
/// let base = 16;
|
|
/// assert_eq!(char_length(base), 2)
|
|
/// ```
|
|
pub fn char_length(base: u32) -> u32 {
|
|
for i in 1..base + 1 {
|
|
let num = base.pow(i);
|
|
if num > 255 {
|
|
return i;
|
|
}
|
|
}
|
|
return u32::MAX;
|
|
}
|
|
}
|