browserslist-rs 0.22.0

Rust-ported Browserslist.
Documentation
use super::{Distrib, QueryResult};
use crate::{Opts, error::Error, parser::SupportKind};
use browserslist_data::caniuse::{
    VersionDetail, features::get_feature_stat, get_browser_stat, to_desktop_name,
};
use either::Either;

const Y: u8 = 1;
const A: u8 = 2;

pub(super) fn supports(name: &str, kind: Option<SupportKind>, opts: &Opts) -> QueryResult {
    let include_partial = matches!(kind, Some(SupportKind::Partially) | None);

    if let Some(feature) = get_feature_stat(name) {
        let distribs = feature
            .iter()
            .filter_map(|(name, versions)| {
                get_browser_stat(name, opts.mobile_to_desktop)
                    .map(|(name, stat)| (name, stat, versions))
            })
            .flat_map(|(name, browser_stat, versions)| {
                let desktop_name = opts
                    .mobile_to_desktop
                    .then_some(to_desktop_name(name))
                    .flatten();
                let Some(desktop_name) = desktop_name else {
                    return Either::Left(
                        versions
                            .spans(browser_stat.len())
                            .filter(|(_, flags)| is_supported(*flags, include_partial))
                            .flat_map(move |(positions, _)| &browser_stat[positions])
                            .map(move |version| Distrib::new(name, version.version())),
                    );
                };

                let mobile_list = get_browser_stat(name, false).map_or(&[][..], |(_, list)| list);
                let mobile_position = move |version: &VersionDetail| {
                    mobile_list
                        .iter()
                        .position(|mobile| mobile.version() == version.version())
                };
                let check_desktop = browser_stat
                    .iter()
                    .rev()
                    .filter(|version| version.released)
                    .find_map(mobile_position)
                    .is_some_and(|position| {
                        is_supported(versions.flag_at(position), include_partial)
                    });
                let desktop = check_desktop
                    .then(|| {
                        feature
                            .get(desktop_name)
                            .zip(get_browser_stat(desktop_name, false))
                    })
                    .flatten();
                Either::Right(browser_stat.iter().enumerate().filter_map(
                    move |(index, version)| {
                        let flags = match mobile_position(version) {
                            Some(position) => versions.flag_at(position),
                            None => {
                                let (desktop_versions, (_, desktop_list)) = desktop?;
                                let position =
                                    (index + desktop_list.len()).checked_sub(browser_stat.len())?;
                                if desktop_list.get(position)?.version() != version.version() {
                                    return None;
                                }
                                desktop_versions.flag_at(position)
                            }
                        };
                        is_supported(flags, include_partial)
                            .then(|| Distrib::new(name, version.version()))
                    },
                ))
            })
            .collect();
        Ok(distribs)
    } else {
        Err(Error::UnknownBrowserFeature(name.to_string()))
    }
}

fn is_supported(flags: u8, include_partial: bool) -> bool {
    flags & Y != 0 || include_partial && flags & A != 0
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        opts::Opts,
        test::{run_compare, should_failed},
    };
    use test_case::test_case;

    #[test_case("supports objectrtc"; "case 1")]
    #[test_case("supports    rtcpeerconnection"; "case 2")]
    #[test_case("supports        arrow-functions"; "case 3")]
    #[test_case("partially supports rtcpeerconnection"; "partially")]
    #[test_case("fully     supports rtcpeerconnection"; "fully")]
    fn default_options(query: &str) {
        run_compare(query, &Opts::default(), None);
    }

    #[test_case("supports filesystem"; "case 1")]
    #[test_case("supports  font-smooth"; "case 2")]
    fn mobile_to_desktop(query: &str) {
        run_compare(
            query,
            &Opts {
                mobile_to_desktop: true,
                ..Default::default()
            },
            None,
        );
    }

    #[test]
    fn invalid() {
        assert_eq!(
            should_failed("supports xxxyyyzzz", &Opts::default()),
            Error::UnknownBrowserFeature(String::from("xxxyyyzzz"))
        );
    }
}