hmd 0.4.13

Custom Markdown Engine for my personal blog.
Documentation
use crate::consts::*;
use crate::utils::into_v16;


/*
`<`s are converted to `&lt` and `&gt`, always!
`>`s are kept untouched because they could be part of a blockquote
backslashes are always escaped.
*/

pub fn escape_htmls(content: &Vec<u16>) -> Vec<u16> {

    let mut result = Vec::with_capacity(content.len() + content.len() / 4);

    for c in content.iter() {

        match *c {
            U16_AMPERSAND => {
                result.push(U16_AMPERSAND);
                result.push(U16_SMALL_A);
                result.push(U16_SMALL_M);
                result.push(U16_SMALL_P);
                result.push(U16_SEMI_COLON);
            },
            U16_LESS_THAN => {
                result.push(U16_AMPERSAND);
                result.push(U16_SMALL_L);
                result.push(U16_SMALL_T);
                result.push(U16_SEMI_COLON);
            },
            U16_DOUBLE_QUOTE => {
                result.push(U16_AMPERSAND);
                result.push(U16_SMALL_Q);
                result.push(U16_SMALL_U);
                result.push(U16_SMALL_O);
                result.push(U16_SMALL_T);
                result.push(U16_SEMI_COLON);
            },
            U16_SINGLE_QUOTE => {
                result.push(U16_AMPERSAND);
                result.push(U16_SMALL_A);
                result.push(U16_SMALL_P);
                result.push(U16_SMALL_O);
                result.push(U16_SMALL_S);
                result.push(U16_SEMI_COLON);
            },
            _ => {
                result.push(*c);
            }
        }
    }

    result
}


pub fn undo_html_escapes(content: &Vec<u16>) -> Vec<u16> {
    
    let mut result = Vec::with_capacity(content.len());
    let mut index = 0;

    while index < content.len() {

        match is_escaped(content, index) {
            None => {
                result.push(content[index]);
            }
            Some((c, i)) => {
                result.push(c);
                index = i;
            }
        }

        index += 1;
    }

    result
}


pub fn is_escaped(content: &Vec<u16>, index: usize) -> Option<(u16, usize)> {

    if content[index] == U16_AMPERSAND && index + 4 < content.len() {

        if content[index + 1] == U16_SMALL_A {

            if content[index + 2] == U16_SMALL_M && content[index + 3] == U16_SMALL_P && content[index + 4] == U16_SEMI_COLON {
                return Some((U16_AMPERSAND, index + 4));
            }

            if content[index + 2] == U16_SMALL_P && content[index + 3] == U16_SMALL_O && content[index + 4] == U16_SMALL_S && index + 5 < content.len() && content[index + 5] == U16_SEMI_COLON {
                return Some((U16_SINGLE_QUOTE, index + 5));
            }

        }

        else if content[index + 1] == U16_SMALL_L && content[index + 2] == U16_SMALL_T && content[index + 3] == U16_SEMI_COLON {
            return Some((U16_LESS_THAN, index + 3));
        }

        else if content[index + 1] == U16_SMALL_Q && content[index + 2] == U16_SMALL_U && content[index + 3] == U16_SMALL_O && content[index + 4] == U16_SMALL_T && index + 5 < content.len() && content[index + 5] == U16_SEMI_COLON {
            return Some((U16_DOUBLE_QUOTE, index + 5));
        }

    }

    None
}


pub fn escape_backslashes(content: &Vec<u16>) -> Vec<u16> {

    let mut index = 0;
    let mut result = Vec::with_capacity(content.len());

    while index < content.len() {

        if content[index] == U16_BACKSLASH {
            result.push(BACKSLASH_ESCAPE_MARKER);

            if index + 1 >= content.len() {
                return result;
            }

            else if content[index + 1] != U16_NEWLINE {
                result.push(u16::MAX - content[index + 1]);
                index += 1;
            }

        }

        else {
            result.push(content[index]);
        }

        index += 1;
    }

    result
}


pub fn undo_backslash_escape(content: &Vec<u16>) -> Vec<u16> {

    let mut index = 0;
    let mut result = Vec::with_capacity(content.len());

    while index < content.len() {

        if content[index] == BACKSLASH_ESCAPE_MARKER {
            result.push(U16_BACKSLASH);

            if index + 1 == content.len() {
                return result;
            }

            else {
                result.push(u16::MAX - content[index + 1]);
                index += 1;
            }

        }

        else {
            result.push(content[index]);
        }

        index += 1;
    }

    result
}


pub fn render_backslash_escape(content: &Vec<u16>) -> Vec<u16> {

    let mut result = Vec::with_capacity(content.len() + content.len() / 4);
    let mut index = 0;

    while index < content.len() {

        if content[index] == BACKSLASH_ESCAPE_MARKER {
            result.push(U16_AMPERSAND);
            result.push(U16_SHARP);

            for num in into_v16(&(u16::MAX - content[index + 1]).to_string()) {
                result.push(num);
            }

            result.push(U16_SEMI_COLON);
            index += 1;
        }

        else {
            result.push(content[index]);
        }

        index += 1;
    }

    result
}