mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-02-23 04:52:28 +00:00
doc & ui-test for FromBody
This commit is contained in:
parent
e7e55514a2
commit
aa9fa0f457
6 changed files with 66 additions and 16 deletions
|
@ -39,6 +39,7 @@ uuid = { version = "0.8.1", optional = true }
|
||||||
diesel = { version = "1.4.4", features = ["postgres"] }
|
diesel = { version = "1.4.4", features = ["postgres"] }
|
||||||
futures-executor = "0.3.4"
|
futures-executor = "0.3.4"
|
||||||
paste = "0.1.12"
|
paste = "0.1.12"
|
||||||
|
trybuild = "1.0.26"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["errorlog"]
|
default = ["errorlog"]
|
||||||
|
|
|
@ -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
|
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;
|
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>;
|
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
|
/// This error type can be used by [`FromBody`](trait.FromBody.html) implementations when there
|
||||||
/// errors.
|
/// is no need to return any errors.
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Error)]
|
#[derive(Clone, Copy, Debug, Error)]
|
||||||
#[error("No Error")]
|
#[error("No Error")]
|
||||||
pub struct FromBodyNoError;
|
pub struct FromBodyNoError;
|
||||||
|
|
10
gotham_restful/tests/ui.rs
Normal file
10
gotham_restful/tests/ui.rs
Normal 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");
|
||||||
|
}
|
12
gotham_restful/tests/ui/from_body_enum.rs
Normal file
12
gotham_restful/tests/ui/from_body_enum.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#[macro_use] extern crate gotham_restful;
|
||||||
|
|
||||||
|
#[derive(FromBody)]
|
||||||
|
enum FromBodyEnum
|
||||||
|
{
|
||||||
|
SomeVariant(Vec<u8>),
|
||||||
|
OtherVariant(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
{
|
||||||
|
}
|
5
gotham_restful/tests/ui/from_body_enum.stderr
Normal file
5
gotham_restful/tests/ui/from_body_enum.stderr
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
error: #[derive(FromBody)] only works for structs
|
||||||
|
--> $DIR/from_body_enum.rs:4:1
|
||||||
|
|
|
||||||
|
4 | enum FromBodyEnum
|
||||||
|
| ^^^^
|
|
@ -21,25 +21,25 @@ struct ParsedFields
|
||||||
|
|
||||||
impl ParsedFields
|
impl ParsedFields
|
||||||
{
|
{
|
||||||
fn from_named<I>(fields : I) -> Result<Self>
|
fn from_named<I>(fields : I) -> Self
|
||||||
where
|
where
|
||||||
I : Iterator<Item = Field>
|
I : Iterator<Item = Field>
|
||||||
{
|
{
|
||||||
let fields = fields.map(|field| (field.ident.unwrap(), field.ty)).collect();
|
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
|
where
|
||||||
I : Iterator<Item = Field>
|
I : Iterator<Item = Field>
|
||||||
{
|
{
|
||||||
let fields = fields.enumerate().map(|(i, field)| (format_ident!("arg{}", i), field.ty)).collect();
|
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::Enum(inum) => Err(inum.enum_token.span()),
|
||||||
Data::Struct(strukt) => Ok(strukt),
|
Data::Struct(strukt) => Ok(strukt),
|
||||||
Data::Union(uni) => Err(uni.union_token.span())
|
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 {
|
let fields = match strukt.fields {
|
||||||
Fields::Named(named) => ParsedFields::from_named(named.named.into_iter())?,
|
Fields::Named(named) => ParsedFields::from_named(named.named.into_iter()),
|
||||||
Fields::Unnamed(unnamed) => ParsedFields::from_unnamed(unnamed.unnamed.into_iter())?,
|
Fields::Unnamed(unnamed) => ParsedFields::from_unnamed(unnamed.unnamed.into_iter()),
|
||||||
Fields::Unit => ParsedFields::from_unit()?
|
Fields::Unit => ParsedFields::from_unit()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut where_clause = quote!();
|
let mut where_clause = quote!();
|
||||||
|
|
Loading…
Add table
Reference in a new issue