Crates.io | serde_extract |
lib.rs | serde_extract |
version | 0.1.0 |
source | src |
created_at | 2022-12-22 22:52:22.609487 |
updated_at | 2022-12-22 22:52:22.609487 |
description | Enables remapping two structs using the Serde framework |
homepage | |
repository | https://github.com/Ten0/serde_extract |
max_upload_size | |
id | 744154 |
size | 39,706 |
Enables turning a value that has Serialize
into a Deserializer
Effectively this enables extracting a struct that implements Deserialize
from a struct that
implements Serialize
.
#[derive(serde_derive::Serialize)]
struct Source<'a> {
a: &'a str,
b: u32,
}
#[derive(Debug, PartialEq, serde_derive::Deserialize)]
struct Extract {
b: u32,
}
assert_eq!(
Extract { b: 3 },
serde_extract::extract(&Source { a: "hello", b: 3 }).unwrap(),
);
Let's say we're in a scenario where we want to implement an SDK where results are paginated, we only need to send
the original query once, but we need to re-send page_size
if it was provided in the original query.
Since the code that manages pagination has no knowledge of the underlying struct, and because adding a page_size
argument to our make_paginated_request
function would be very un-ergonomic because (let's say) it would be very
rarely used and it's nicer to specify it in the same struct as the rest of the query parameters, this is a good
use-case for this crate.
// This will be our original query
#[derive(serde_derive::Serialize)]
struct SomeSpecificRequest {
field_a: &'static str,
page_size: usize,
}
// Let's say make_request is our generic function that makes a call to the server
make_paginated_request(&SomeSpecificRequest {
field_a: "hello!",
page_size: 2,
})
.expect("Failed to make request");
fn make_paginated_request<S: serde::Serialize>(
serializable: &S,
) -> Result<(), Box<dyn std::error::Error>> {
#[derive(serde_derive::Deserialize)]
struct MaybePageSize {
page_size: Option<usize>,
}
// We will reuse the page size for the subsequent paginated requests if it was
// provided in the original query, so we need to extract it
let page_size_for_this_request =
serde_extract::extract::<MaybePageSize, _>(serializable)?.page_size;
// this works:
assert_eq!(page_size_for_this_request, Some(2));
// Make request...
Ok(())
}
Serializer
for each element called for by the Visitor
through MapAccess
)map
s is currently unsupported. Specifically, currently we can only
extract struct fields if the fields names are hinted by deserialize_struct
.
(This enables driving the Serializer
only as many times as there are fields to extract. In practice if both
sides are regular structs, the optimizer probably turns that into zero-cost extraction. In theory again, support
for deserializing into maps could be added with O(n²) complexity where n is the number of input fields.)