use axum::extract::FromRef;
use axum::extract::State;
use axum::routing::get;
use axum::Router;
use std::sync::Arc;
use tokio::sync::RwLock;
use std::fmt::Debug;

// Simple state

#[derive(Clone, Debug)]
pub struct AppState {
    substate1: SubState1,
}

#[derive(Clone, Debug)]
pub struct SubState1 {
    mutcounter: Arc<RwLock<MutCounter>>,
}

#[derive(Clone, Debug)]
pub struct MutCounter {
    counter: u32,
}

impl MutCounter {
    pub fn inc(&mut self) {
        self.counter += 1;
    }

    pub fn new() -> Self {
        MutCounter { counter: 3 }
    }
}

impl FromRef<AppState> for SubState1 {
    fn from_ref(app_state: &AppState) -> SubState1 {
        app_state.substate1.clone()
    }
}

// End simple state

// Generic state
//
#[derive(Clone, Debug)]
pub struct GenAppState<GSS: Clone + GenMutCounter> {
    substate1: GenSubState1<GSS>
}

#[derive(Clone, Debug)]
pub struct GenSubState1<GSS: Clone + GenMutCounter> {
    mutcounter: Arc<RwLock<GSS>>
}

impl <GSS: Clone + GenMutCounter> FromRef<GenAppState<GSS>> for GenSubState1<GSS> {
    fn from_ref(app_state: &GenAppState<GSS>) -> GenSubState1<GSS> {
        app_state.substate1.clone()
    }
}



pub trait GenMutCounter {
    fn inc(&mut self);
}

// End generic state

#[derive(Clone, Debug)]
pub struct GenMutCounterU32 {
    counter: u32
}

impl GenMutCounterU32 {
    pub fn new() -> Self {
        GenMutCounterU32 {
            counter: 4
        }
    }
}

impl  GenMutCounter for GenMutCounterU32 {
    fn inc(&mut self) {
        self.counter += 1;
    }
}


#[tokio::main]
async fn main() {
    let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
        .await
        .unwrap();
    axum::serve(listener, app()).await.unwrap();
    println!("Hello, world!");
}

fn app() -> Router {
    let state = AppState {
        substate1: SubState1 {
            mutcounter: Arc::new(RwLock::new(MutCounter::new())),
        },
    };

    let state2 = GenAppState {
        substate1: GenSubState1 {
            mutcounter: Arc::new(RwLock::new(GenMutCounterU32::new()))
        }
    };
    let app = Router::new()
        .route("/", get(root3))
        .with_state(state2.clone());
    app
}

pub async fn root(State(app_state): State<AppState>) -> &'static str {
    dbg!(&app_state);
    let mut a = app_state.substate1.mutcounter.write().await;
    a.inc();
    "AAAAAAAAAAAAAAAAA"
}

pub async fn root2(State(sub_state1): State<SubState1>) -> &'static str {
    dbg!(&sub_state1);
    let mut a = sub_state1.mutcounter.write().await;
    a.inc();
    "AAAAAAAAAAAAAAAAA"
}

pub async fn root3<GMC>(State(gen_sub_state1): State<GenSubState1<GMC>>) -> &'static str
where
     GMC: GenMutCounter + Clone + Debug

{
    dbg!(&gen_sub_state1);
    let mut a = gen_sub_state1.mutcounter.write().await;
    a.inc();
    "AAAAAAAAAAAAAAAAA"
}
#[cfg(test)]
mod tests {
    use super::*;
    use axum::body::Body;
    use axum::http::{Request, StatusCode};
    use tower::{Service, ServiceExt};

    #[tokio::test]
    async fn hw_test() {
        let app = app();
        for _ in 0..3 {
            let response = app
                .clone()
                .oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())
                .await
                .unwrap();
            assert_eq!(response.status(), StatusCode::OK);
        }
    }
}

Изменить пасту