Home > Enterprise >  How does one implement an Iterator for a an Object that has generic types?
How does one implement an Iterator for a an Object that has generic types?

Time:02-13

So I have an object called DetailedResponse<T>. Now I want to use this for an API where I can pass some data into it. Let's say this is the implementation for DetailedResponse

#[derive(serde::Deserialize, serde::Serialize)]
pub struct DetailedResponse<T> {
    pub data: Option<T>,
    pub success: bool,
    pub message: String,
}

impl<T> DetailedResponse<T> {
    pub fn new() -> DetailedResponse<T> {
        DetailedResponse {
            data: None,
            success: false,
            message: "".to_string(),
        }
    }
}

And now in the API I want to use actix::Json to map some data lests say: DetailedResponse<Vec<i16>> and I want to implement the response in code like this:

let response = DetailedResponse<Vec<i16>>::new();
// Do something
response.map(Json)

I know I need to implement an Iterator trait for detailed response but I haven't seen good examples for what I want to accomplish. What I am imagining is that I will need to do something like this:

pub struct DetailedResponseIter<T> {
    // stuck here
}

impl<'a, T> DetailedResponseIter<T> {
    type Item = DetailedResponse<T>

    // Also Stuck here.
}

Thank you for your help and I will edit any more needed information.

CodePudding user response:

Try something like this:

impl<T> Iterator for /*...*/ {
    type Item = /*...*/;
    
    fn next(&mut self) -> Option<Self::Item> {
        // ...
    }
}

See https://doc.rust-lang.org/std/iter/index.html#implementing-iterator, https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods, and https://doc.rust-lang.org/reference/items/implementations.html#generic-implementations.

P.S. What is your iterator intended to do?

CodePudding user response:

So taking a hint from jmb, I did some more digging and the answer is pretty simple. And the error I was getting was not as clear as I was thinking. Here is the Actual Code block I am working with:


#[actix_web::get("/party")]
async fn parties(db: Data<PartyRepo>) 
    -> Result<
        Json<DetailedResponse<Vec<PartyEntity>>>,
        InternalError<StdErr>
    >
{
    let mut response: DetailedResponse<Vec<PartyEntity>> = DetailedResponse::new();
    
    let data = db.all().await;
    match data {
        Ok(value) => {
            response.data = Some(value);
            response.success = true;
            response.message = format!("APi Request Successful on {}/{}",
                std::env::var("SERVER_URL").unwrap(),
                std::env::var("PARTY_CONTROLLER_PORT").unwrap()
            );
        }
        Err(e) => {
            response.success = false;
            response.message = e.to_string();
        }
    }
    Ok(Json(response))
}

You can really just map the data within the Json and aslong as DetailedResponse has #[derive(serde::Deserialize)] Tag it should do the work. As always RFM. Also thank you to Solomon Ucko for helping me stumble on to this lol.

  • Related