Need advice with some Rust code

Hi!

I'm new to Rust programming.

I try to write a lib while reading the Rust book to practice day one.

Despite I get things working, I'd like to know if I take the good direction before going further.

If an experienced Rust developer could review this PR for common mistakes or even give advices, I would really appreciate :).

I did a PR to make commenting easyer: https://github.com/nfroidure/rust-siso/pull/1

Thanks for reading

PS: Tried to post this in #rust-beginners but blocked as spam :confused:

Did a short review! You could also try using clippy for linting https://github.com/rust-lang-nursery/rust-clippy#usage.

2 Likes

I try to implement trait objects for the path nodes but I'm stuck on the following error:

error[E0308]: mismatched types
   --> src/lib.rs:186:23
    |
186 |             .register(route1.as_slice(), String::from("test3"))
    |                       ^^^^^^^^^^^^^^^^^ expected trait MatchPathNode, found struct `std::string::String`
    |
    = note: expected type `&[std::boxed::Box<MatchPathNode + 'static>]`
               found type `&[std::boxed::Box<std::string::String>]

https://github.com/nfroidure/rust-siso/blob/wip/trait_object_attempt/src/lib.rs#L157-L174

If I understand the error message, the compiler thinks that the String struct hasn't the MatchPathNode trait implemented but it is here: https://github.com/nfroidure/rust-siso/blob/wip/trait_object_attempt/src/lib.rs#L83-L93

Maybe it has something to do with the `'static' word following my trait name but I have no clue what it means. What am i missing here?

A &[Box<String>] has a different representation/layout than &[Box<MatchPathNode>]. Namely, the latter is a slice of trait objects (the box has a fat ptr inside), whereas the former is a slice of normal thin ptrs (inside the box).

You want to change the route1 declaration to:

let route1: Vec<Box<MatchPathNode>> = vec![Box::new(String::from("foo")), Box::new(String::from("bar"))];
// or
let route1 = vec![Box::new(String::from("foo")) as Box<MatchPathNode>, Box::new(String::from("bar"))];

So the compiler knows you’re creating a vec of trait objects.

1 Like

Thank you! It fixed the compilation issue. Now my concern is about the heavy surface API of the resulting library despite not feature complete yet plus the performance overhead of dynamic dispatch.

What is the convention in the Rust community? Do you think allowing custom behavior make sense for a routing crate or is it better to juste allow an enum of fixed types for the router node declaration?

To be honest, I’ve not looked in detail into what you’re building. But, to your question above, you can combine the two approaches with an enum:

enum RouteNode {
   String(String),
   Pattern(PathPattern),
   Custom(Box<MatchPathNode>),
}

I’d not worry about performance overhead of dynamic dispatch just yet - it may not matter in the end once you’ve built out the rest of the functionality. You can always redesign later, but at least you’ll have something working to go off and it’ll be a good performance baseline to compare against.

1 Like