Rust's type state pattern is making me sad. It sounds like the solution to my problem, but every time I try to implement it I get some new wall to run into.
I'm trying to write a library for interacting with this fairly old API I use in my job. It has some common parameters, but most of the parameters depend on the function you want to call. So I was really trying to do something where you'd use it like:
let call = myapi::new().function(function1).param1(whatever)... and so on
Type state seemed like a good fit here, adding training wheels to the library so you can only call parameters that make sense. I had imagined it something like this:
//ton of unit structs representing the old api functions
struct func1 {}
struct func2 {}
...
//a trait to mark them all as valid
trait validfunc {}
//all the impl blocks
impl validfunc for func1 {}
impl validfunc for func2 {}
//the actual struct for my data
struct myapi<S: validfunc> {
marker: PhantomData<S>,
param1: Option<String>,
param2: Option<u32>,
etc....
}
Something like that, then I could do impl blocks depending on what state it was in:
impl myapi<func1> {
fn param1(input) {
yada yada
}
}
impl myapi<func2> {
fn param1(input) {
yada yada
}
fn param2(input) {
yada yada again
}
}
Finally, this old API I'm interacting with allows you to use create your own custom calls, so one goal of my library was that a person could write a new unit struct and create their own impl blocks easily. I was even considering writing proc macros to generate the common parameters to make it easy to add them.
Clearly this doesn't work since I'm here asking. But I'm hoping someone can see what I was trying to accomplish and offer a different approach, because I'm sorta stuck.
Some other things that might matter.
- This old API has almost 200 functions, so there's quite a lot of variety in how it can be called.
- Once I create the call and send it, I get a stream of bytes back. How I decode that depends on what function was called, so I need to carry that state over to my response.
- If my library doesn't allow for custom calls, it's not worth it. There's other utilities out there for the standard set of functions, I need the ability for a user to add their own without it being too huge an effort.
Anyone have any ideas?