-
Notifications
You must be signed in to change notification settings - Fork 77
Description
I was trying to find a way to encode URL parameters into definite enums so there's no guessing if a parameter is valid or not, but the solution I figured out doesn't work :(
Here is the code and its output. As you can see, it works with the JSON serializer and formats the output into a map, but the url_encoder doesn't exhibit the same behaviour?
A possible (dirty) solution to my problem in particular would be to first serialize my custom type into a JSON value and then pass that into the URL serializer. There isn't really a problem with this solution besides being clunky and unintuitive, but I was wondering if the url_encoder could be expanded to include serialization targets that are able to be coerced into struct/map representations. Just like how the JSON output is a dictionary, so too could the url_encoder represent this case as a map.
I'm not super familiar with how serializers work, sorry 😞
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::to_value;
#[derive(Serialize, Deserialize)]
enum Params {
EnumA(EnumA),
EnumB(EnumB),
}
trait IntoParam {
fn into_param(self) -> Params;
}
// trait FromParam {
// fn from_param(param: Params) -> Self;
// }
#[derive(Serialize, Deserialize)]
// #[serde(tag = "EnumA")]
enum EnumA {
VarA,
VarB,
}
impl IntoParam for EnumA {
fn into_param(self) -> Params {
Params::EnumA(self)
}
}
#[derive(Serialize, Deserialize)]
// #[serde(tag = "EnumB")]
enum EnumB {
VarC,
#[serde(untagged)]
Base(EnumA),
}
impl IntoParam for EnumB {
fn into_param(self) -> Params {
Params::EnumB(self)
}
}
fn main() -> () {
println!("EnumA::VarA.into_param(), {}", to_value(EnumA::VarA.into_param()).unwrap().to_string());
println!("EnumA::VarB.into_param(), {}", to_value(EnumA::VarB.into_param()).unwrap().to_string());
println!("EnumB::VarC.into_param(), {}", to_value(EnumB::VarC.into_param()).unwrap().to_string());
println!("EnumB::Base(EnumA::VarA).into_param(), {}", to_value(EnumB::Base(EnumA::VarA).into_param()).unwrap().to_string());
let client = Client::new();
let request = client.get("https://google.com").query(&EnumB::Base(EnumA::VarA).into_param()).build().unwrap();
println!("Reqwest url, {}", request.url())
}
EnumA::VarA.into_param(), {"EnumA":"VarA"}
EnumA::VarB.into_param(), {"EnumA":"VarB"}
EnumB::VarC.into_param(), {"EnumB":"VarC"}
EnumB::Base(EnumA::VarA).into_param(), {"EnumB":"VarA"}
thread 'main' panicked at src/scripts/analyze_endpoints.rs:58:104:
calledResult::unwrap()on anErrvalue: reqwest::Error { kind: Builder, source: Custom("top-level serializer supports only maps and structs") }
stack backtrace:
0: rust_begin_unwind
at /rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/std/src/panicking.rs:645:5
1: core::panicking::panic_fmt
at /rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/panicking.rs:72:14
2: core::result::unwrap_failed
at /rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/result.rs:1654:5
3: core::result::Result<T,E>::unwrap
at /rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/result.rs:1077:23
4: analyze_endpoints::main
at ./src/scripts/analyze_endpoints.rs:58:17
5: core::ops::function::FnOnce::call_once
at /rustc/9b00956e56009bab2aa15d7bff10916599e3d6d6/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run withRUST_BACKTRACE=fullfor a verbose backtrace.