Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return unboxed filters #132

Closed
bestouff opened this issue Nov 4, 2018 · 9 comments
Closed

Return unboxed filters #132

bestouff opened this issue Nov 4, 2018 · 9 comments

Comments

@bestouff
Copy link

bestouff commented Nov 4, 2018

Would it be possible to return routes without using boxed ? For now it requires warp::generic::Either which is private (see #5).

@seanmonstar
Copy link
Owner

It is possible in some cases, like fn foo() -> impl Filter<Extract=(i32,), Error=Rejection> { warp::path::param() }. However, you can't (yet) nest impl Traits (so returning impl Filter<Extract=impl Reply> isn't legal yet), so that is what boxed is for.

@kamek-pf
Copy link
Contributor

kamek-pf commented Nov 9, 2018

Seems to work on current stable (1.30.1) :

fn hello_filter() -> impl Filter<Extract = (impl Reply), Error = Rejection> + Copy {
    warp::get2()
        .and(path!("hello"))
        .map(|| "hello")
}

I wish we had a better way to write that kind of signature though, this looks particularly noisy to me.

@seanmonstar
Copy link
Owner

Seeing as it's possible to do as the issue title says, I'm going to close. For the comment about making Either public, see #5.

@bestouff
Copy link
Author

Ok my bad, in fact it doesn't work in traits but that's an other problem (impl in traits).

@bestouff
Copy link
Author

Any hint why this doesn't work then ?

    pub fn routes<T: EndPoint>(endpoint: T, db: Db<T>) -> impl Filter<Extract = (impl Reply), Error = Rejection> + Copy {
        let db = warp::any().map(move || db.clone());
        let path = warp::path(T::name());
        let path_index = path.and(warp::path::end());
        let path_id = path
            .and(warp::path::param::<u64>())
            .and(warp::path::end());

        let json_body = warp::body::content_length_limit(1024 * 16).and(warp::body::json());

        let list = warp::get2()
            .and(path_index)
            .and(db.clone())
            .map(list::<T>);

        let create = warp::post2()
            .and(path_index)
            .and(json_body)
            .and(db.clone())
            .and_then(create::<T>);

        let update = warp::put2()
            .and(path_index)
            .and(json_body)
            .and(db.clone())
            .and_then(update::<T>);

        let delete = warp::delete2()
            .and(path_id)
            .and(db.clone())
            .and_then(delete::<T>);

        // Combine our endpoints, since we want requests to match any of them:
        let api = list.or(create).or(update).or(delete);
        api
    }
    fn list<T: EndPoint>(db: Db<T>) -> impl Filter<Extract = (impl Reply), Error = Rejection> + Copy {
        warp::reply::json(&*db.lock().unwrap())
    }

This fails with:

error[E0599]: no method named `map` found for type `warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>>` in the current scope
  --> src/main.rs:35:14                                                                                               
   |                                                                                                                  
35 |             .map(list::<T>);                                                                                     
   |              ^^^                                                                                                 
   |                                                                                                                  
   = note: the method `map` exists but the following trait bounds were not satisfied:                                 
           `warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>> : warp::Filter`
           `&warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>> : warp::Filter`
           `&mut warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>> : warp::Filter`
           `&mut warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>> : std::iter::Iterator`
...

@seanmonstar
Copy link
Owner

Filter::map takes a function that returns a particular type. It looks like list wants to return a new impl Filter.

What if you changed it to:

fn list<T: EndPoint>(db: Db<T>) -> impl Reply {
    warp::reply::json(&*db.lock().unwrap())
}

@bestouff
Copy link
Author

That's what I had first, I changed it to match what was given in this "thread". But it's the same problem:

    fn list<T: EndPoint>(db: Db<T>) -> impl warp::Reply {
        warp::reply::json(&*db.lock().unwrap())
    }

gives

error[E0599]: no method named `map` found for type `warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>>` in the current scope
  --> src/main.rs:35:14                                                                                   
   |                                                                                                      
35 |             .map(list::<T>);                                                                         
   |              ^^^                                                                                     
   |                                                                                                      
   = note: the method `map` exists but the following trait bounds were not satisfied:                     
           `warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>> : warp::Filter`
           `&warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>> : warp::Filter`
           `&mut warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>> : warp::Filter`
           `&mut warp::filter::and::And<warp::filter::and::And<impl warp::Filter+std::marker::Copy, warp::filter::and::And<impl warp::Filter+std::marker::Copy, impl warp::Filter+std::marker::Copy>>, warp::filter::map::Map<impl warp::Filter+std::marker::Copy, [closure@src/main.rs:23:34: 23:52 db:_]>> : std::iter::Iterator`

@seanmonstar
Copy link
Owner

Hm, it's claiming that .and(db) doesn't implement Filter. I see an extra bounds of Send on the impl for And, it might be that you need a T: Endpoint + Send.

@bestouff
Copy link
Author

Where so ? I tried pub type Db<T: EndPoint + Send> which gives the same error, and pub fn routes<T: EndPoint + std::fmt::Debug + Send>(endpoint: T, db: Db<T>) which seems to open another can of worms by requiring that EndPoint's types are Copy...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants