1
0
Fork 0
mirror of https://gitlab.com/msrd0/gotham-restful.git synced 2025-02-22 20:52:27 +00:00

doc & ui-test for FromBody

This commit is contained in:
Dominic 2020-05-05 19:31:02 +02:00
parent e7e55514a2
commit aa9fa0f457
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
6 changed files with 66 additions and 16 deletions

View file

@ -39,6 +39,7 @@ uuid = { version = "0.8.1", optional = true }
diesel = { version = "1.4.4", features = ["postgres"] }
futures-executor = "0.3.4"
paste = "0.1.12"
trybuild = "1.0.26"
[features]
default = ["errorlog"]

View file

@ -43,13 +43,36 @@ impl<T : ResourceType + Serialize> ResponseBody for T
}
/// This trait must be implemented by every type that can be used as a request body. It allows
/// to create the type from a hyper body chunk and it's content type.
/**
This trait should be implemented for every type that can be built from an HTTP request body
plus its media type. For most use cases it is sufficient to derive this trait, you usually
don't need to manually implement this. Therefore, make sure that the first variable of
your struct can be built from [`Bytes`], and the second one can be build from [`Mime`].
If you have any additional variables, they need to be `Default`. This is an example of
such a struct:
```rust
# #[macro_use] extern crate gotham_restful;
# use gotham_restful::*;
#[derive(FromBody, RequestBody)]
#[supported_types(mime::IMAGE_GIF, mime::IMAGE_JPEG, mime::IMAGE_PNG)]
struct RawImage {
content: Vec<u8>,
content_type: Mime
}
```
[`Bytes`]: ../bytes/struct.Bytes.html
[`Mime`]: ../mime/struct.Mime.html
*/
pub trait FromBody : Sized
{
/// The error type returned by the conversion if it was unsuccessfull. When using the derive
/// macro, there is no way to trigger an error, so
/// [`FromBodyNoError`](struct.FromBodyNoError.html) is used here.
type Err : Error;
/// Create the request body from a raw body and the content type.
/// Perform the conversion.
fn from_body(body : Bytes, content_type : Mime) -> Result<Self, Self::Err>;
}
@ -63,9 +86,8 @@ impl<T : DeserializeOwned> FromBody for T
}
}
/// This error type can be used by `FromBody` implementations when there is no need to return any
/// errors.
/// This error type can be used by [`FromBody`](trait.FromBody.html) implementations when there
/// is no need to return any errors.
#[derive(Clone, Copy, Debug, Error)]
#[error("No Error")]
pub struct FromBodyNoError;

View file

@ -0,0 +1,10 @@
use trybuild::TestCases;
#[test]
fn ui()
{
let t = TestCases::new();
// always enabled
t.compile_fail("tests/ui/from_body_enum.rs");
}

View file

@ -0,0 +1,12 @@
#[macro_use] extern crate gotham_restful;
#[derive(FromBody)]
enum FromBodyEnum
{
SomeVariant(Vec<u8>),
OtherVariant(String)
}
fn main()
{
}

View file

@ -0,0 +1,5 @@
error: #[derive(FromBody)] only works for structs
--> $DIR/from_body_enum.rs:4:1
|
4 | enum FromBodyEnum
| ^^^^

View file

@ -21,25 +21,25 @@ struct ParsedFields
impl ParsedFields
{
fn from_named<I>(fields : I) -> Result<Self>
fn from_named<I>(fields : I) -> Self
where
I : Iterator<Item = Field>
{
let fields = fields.map(|field| (field.ident.unwrap(), field.ty)).collect();
Ok(Self { fields, named: true })
Self { fields, named: true }
}
fn from_unnamed<I>(fields : I) -> Result<Self>
fn from_unnamed<I>(fields : I) -> Self
where
I : Iterator<Item = Field>
{
let fields = fields.enumerate().map(|(i, field)| (format_ident!("arg{}", i), field.ty)).collect();
Ok(Self { fields, named: false })
Self { fields, named: false }
}
fn from_unit() -> Result<Self>
fn from_unit() -> Self
{
Ok(Self { fields: Vec::new(), named: false })
Self { fields: Vec::new(), named: false }
}
}
@ -53,12 +53,12 @@ pub fn expand_from_body(input : DeriveInput) -> Result<TokenStream>
Data::Enum(inum) => Err(inum.enum_token.span()),
Data::Struct(strukt) => Ok(strukt),
Data::Union(uni) => Err(uni.union_token.span())
}.map_err(|span| Error::new(span, "#[derive(FromBody)] only works for enums"))?;
}.map_err(|span| Error::new(span, "#[derive(FromBody)] only works for structs"))?;
let fields = match strukt.fields {
Fields::Named(named) => ParsedFields::from_named(named.named.into_iter())?,
Fields::Unnamed(unnamed) => ParsedFields::from_unnamed(unnamed.unnamed.into_iter())?,
Fields::Unit => ParsedFields::from_unit()?
Fields::Named(named) => ParsedFields::from_named(named.named.into_iter()),
Fields::Unnamed(unnamed) => ParsedFields::from_unnamed(unnamed.unnamed.into_iter()),
Fields::Unit => ParsedFields::from_unit()
};
let mut where_clause = quote!();