#struct #serialization #serde #extract #framework #deserialize #deserializer

serde_extract

Enables remapping two structs using the Serde framework

1 unstable release

0.1.0 Dec 22, 2022

#1884 in Encoding

LGPL-3.0-only

27KB
588 lines

serde_extract

Crates.io License

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.

Usage

TL;DR

#[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(),
);

More realistic example

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(())
}

Limitations

  • Sequences are not supported for now (although support could theoritically be added, algorithmic complexity of generated code would be O(n²) where n is the number of elements in the sequence because we would need to re-drive the Serializer for each element called for by the Visitor through MapAccess)
  • For the same reason, deserializing into maps 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.)

Dependencies

~115–350KB

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy