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:
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"] }
|
||||
futures-executor = "0.3.4"
|
||||
paste = "0.1.12"
|
||||
trybuild = "1.0.26"
|
||||
|
||||
[features]
|
||||
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
|
||||
{
|
||||
/// 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;
|
||||
|
|
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
|
||||
{
|
||||
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!();
|
||||
|
|
Loading…
Add table
Reference in a new issue