redirectionio 2.5.2

Redirection IO Library to handle matching rule, redirect and filtering headers and body.
use crate::router::request_matcher::HeaderValueCondition;
use crate::router::{Route, RouteData};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RouteTrace<T: RouteData> {
    traces: Vec<Trace<T>>,
    routes: Vec<Route<T>>,
    final_route: Option<Route<T>>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Trace<T: RouteData> {
    matched: bool,
    executed: bool,
    count: u64,
    #[serde(flatten)]
    info: TraceInfo<T>,
    children: Vec<Trace<T>>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "type")]
pub enum TraceInfo<T: RouteData> {
    Scheme { request: String, against: Option<String> },
    HostStatic { request: String, against: Option<String> },
    HostRegex,
    Ip { request: String, against: String },
    Method { request: String, against: Option<String> },
    HeaderGroup { conditions: Vec<TraceInfoHeaderCondition> },
    PathAndQueryStatic { request: String },
    PathAndQueryRegex,
    Regex { request: String, against: String },
    Storage { routes: Vec<Route<T>> },
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TraceInfoHeaderCondition {
    pub result: Option<bool>,
    pub name: String,
    pub condition: HeaderValueCondition,
    pub cached: bool,
}

impl<T: RouteData> RouteTrace<T> {
    pub fn new(traces: Vec<Trace<T>>, routes: Vec<Route<T>>, final_route: Option<Route<T>>) -> RouteTrace<T> {
        RouteTrace {
            traces,
            routes,
            final_route,
        }
    }
}

impl<T: RouteData> Trace<T> {
    pub fn new(matched: bool, executed: bool, count: u64, children: Vec<Trace<T>>, info: TraceInfo<T>) -> Trace<T> {
        Trace {
            matched,
            executed,
            count,
            info,
            children,
        }
    }

    pub fn get_routes_from_traces(traces: &[Trace<T>]) -> Vec<&Route<T>> {
        let mut routes = Vec::new();

        for trace in traces {
            if let TraceInfo::Storage { routes: routes_stored } = &trace.info {
                routes.extend(routes_stored.iter().collect::<Vec<_>>());
            }

            if !trace.children.is_empty() {
                routes.extend(Trace::get_routes_from_traces(&trace.children));
            }
        }

        routes
    }
}