leptos_router 0.0.2

Router for the Leptos web framework.
Documentation
use std::borrow::Cow;

#[doc(hidden)]
#[cfg(not(feature = "ssr"))]
pub fn expand_optionals(pattern: &str) -> Vec<Cow<str>> {
    use wasm_bindgen::JsValue;

    #[allow(non_snake_case)]
    let OPTIONAL_RE = js_sys::RegExp::new(OPTIONAL, "");
    #[allow(non_snake_case)]
    let OPTIONAL_RE_2 = js_sys::RegExp::new(OPTIONAL_2, "");

    let captures = OPTIONAL_RE.exec(pattern);
    match captures {
        None => vec![pattern.into()],
        Some(matched) => {
            let start: usize = js_sys::Reflect::get(&matched, &JsValue::from_str("index"))
                .unwrap()
                .as_f64()
                .unwrap() as usize;
            let mut prefix = pattern[0..start].to_string();
            let mut suffix = &pattern[start + matched.get(1).as_string().unwrap().len()..];
            let mut prefixes = vec![prefix.clone()];

            prefix += &matched.get(1).as_string().unwrap();
            prefixes.push(prefix.clone());

            while let Some(matched) = OPTIONAL_RE_2.exec(suffix.trim_start_matches('?')) {
                prefix += &matched.get(1).as_string().unwrap();
                prefixes.push(prefix.clone());
                suffix = &suffix[matched.get(0).as_string().unwrap().len()..];
            }

            expand_optionals(suffix)
                .iter()
                .fold(Vec::new(), |mut results, expansion| {
                    results.extend(prefixes.iter().map(|prefix| {
                        Cow::Owned(prefix.clone() + expansion.trim_start_matches('?'))
                    }));
                    results
                })
        }
    }
}

#[doc(hidden)]
#[cfg(feature = "ssr")]
pub fn expand_optionals(pattern: &str) -> Vec<Cow<str>> {
    use regex::Regex;

    lazy_static::lazy_static! {
        pub static ref OPTIONAL_RE: Regex = Regex::new(OPTIONAL).expect("could not compile OPTIONAL_RE");
        pub static ref OPTIONAL_RE_2: Regex = Regex::new(OPTIONAL_2).expect("could not compile OPTIONAL_RE_2");
    }

    let captures = OPTIONAL_RE.find(pattern);
    match captures {
        None => vec![pattern.into()],
        Some(matched) => {
            let mut prefix = pattern[0..matched.start()].to_string();
            let captures = OPTIONAL_RE.captures(pattern).unwrap();
            let mut suffix = &pattern[matched.start() + captures[1].len()..];
            let mut prefixes = vec![prefix.clone()];

            prefix += &captures[1];
            prefixes.push(prefix.clone());

            while let Some(captures) = OPTIONAL_RE_2.captures(suffix.trim_start_matches('?')) {
                prefix += &captures[1];
                prefixes.push(prefix.clone());
                suffix = &suffix[captures[0].len()..];
            }

            expand_optionals(suffix)
                .iter()
                .fold(Vec::new(), |mut results, expansion| {
                    results.extend(prefixes.iter().map(|prefix| {
                        Cow::Owned(prefix.clone() + expansion.trim_start_matches('?'))
                    }));
                    results
                })
        }
    }
}

const OPTIONAL: &str = r#"(/?:[^/]+)\?"#;
const OPTIONAL_2: &str = r#"^(/:[^/]+)\?"#;