cargo-nidus 1.0.0

Command-line project generator and inspection tooling for Nidus applications.
use crate::routes::DiscoveredRoute;

pub(crate) fn sort_discovered_routes(routes: &mut [DiscoveredRoute]) {
    routes.sort_by(|left, right| {
        left.path
            .cmp(&right.path)
            .then_with(|| method_rank(&left.method).cmp(&method_rank(&right.method)))
            .then_with(|| left.method.cmp(&right.method))
    });
}

fn method_rank(method: &str) -> usize {
    ["get", "post", "put", "patch", "delete"]
        .iter()
        .position(|candidate| *candidate == method)
        .unwrap_or(usize::MAX)
}

#[cfg(test)]
mod tests {
    use super::sort_discovered_routes;
    use crate::routes::DiscoveredRoute;

    #[test]
    fn discovered_routes_are_sorted_by_path_then_http_method() {
        let mut routes = vec![
            route("delete", "/users/{id}"),
            route("post", "/users"),
            route("get", "/health"),
            route("get", "/users"),
        ];

        sort_discovered_routes(&mut routes);

        let ordered = routes
            .into_iter()
            .map(|route| (route.method, route.path))
            .collect::<Vec<_>>();
        assert_eq!(
            ordered,
            [
                ("get".to_owned(), "/health".to_owned()),
                ("get".to_owned(), "/users".to_owned()),
                ("post".to_owned(), "/users".to_owned()),
                ("delete".to_owned(), "/users/{id}".to_owned()),
            ]
        );
    }

    fn route(method: &str, path: &str) -> DiscoveredRoute {
        DiscoveredRoute {
            method: method.to_owned(),
            path: path.to_owned(),
            summary: None,
            tags: Vec::new(),
            response_status: None,
            request_schema: None,
            response_schema: None,
            guards: Vec::new(),
            pipes: Vec::new(),
            validates: false,
        }
    }
}