rulet 2.0.0

A rusty figlet implementation
Documentation
use std::{cmp::Ordering, collections::HashMap};

use figfont::{Layout, SubCharacter};

/// Gives the correct character for smushing the right subcharacter into the left one, following the rules given in the layout
pub fn smush_subchars(layout: Layout, left: &SubCharacter, right: &SubCharacter) -> SubCharacter {
    // underscore smushing
    if layout.contains(Layout::HORIZONTAL_LOWLINE)
        && *right == SubCharacter::Symbol("_".to_string())
    {
        let replaced_by = ["|", "/", "\\", "[", "]", "{", "}", "(", ")", "<", ">"];
        if let SubCharacter::Symbol(c) = left {
            if replaced_by.contains(&c.as_str()) {
                return left.clone();
            }
        }
    }
    // Hierarchy smushing
    if layout.contains(Layout::HORIZONTAL_HIERARCHY) {
        if let (SubCharacter::Symbol(a), SubCharacter::Symbol(b)) = (left, right) {
            let priority = HashMap::from([
                ("|", 0),
                ("/", 1),
                ("\\", 1),
                ("[", 2),
                ("]", 2),
                ("{", 3),
                ("}", 3),
                ("(", 4),
                (")", 4),
                ("<", 5),
                (">", 5),
            ]);
            let chosen: Option<SubCharacter> = {
                let p_l = priority.get(&a.as_ref());
                let p_r = priority.get(&b.as_ref());
                if let (Some(p_l), Some(p_r)) = (p_l, p_r) {
                    match p_l.cmp(p_r) {
                        Ordering::Equal => None,
                        Ordering::Greater => Some(left.clone()),
                        Ordering::Less => Some(right.clone()),
                    }
                } else {
                    None
                }
            };
            if let Some(c) = chosen {
                return c;
            }
        }
    }

    // opposite pair smushing
    if layout.contains(Layout::HORIZONTAL_PAIR)
        && matches!((left, right),(SubCharacter::Symbol(a), SubCharacter::Symbol(b)) if matches!((a.as_str(),b.as_str()), ("(", ")") | (")", "(") | ("{", "}") | ("}", "{") | ("[", "]") | ("]", "[")))
    {
        return SubCharacter::Symbol("|".to_string());
    }
    // big X smushing
    if layout.contains(Layout::HORIZONTAL_BIGX) {
        if let (SubCharacter::Symbol(a), SubCharacter::Symbol(b)) = (left, right) {
            let sym = match (a.as_str(), b.as_str()) {
                ("/", "\\") => "|",
                ("\\", "/") => "Y",
                (">", "<") => "X",
                _ => "",
            };
            if !sym.is_empty() {
                return SubCharacter::Symbol(sym.to_string());
            }
        }
    }

    if *right == SubCharacter::Symbol(" ".to_string()) {
        left.clone()
    } else {
        right.clone()
    }
}