mirror of https://github.com/rwf2/Rocket.git
Change meaning of `Option`
This commit is contained in:
parent
1f82d4bbcd
commit
872595b8fa
|
@ -415,12 +415,14 @@ impl<'r, T: FromData<'r> + 'r> FromData<'r> for Result<T, T::Error> {
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'r, T: FromData<'r>> FromData<'r> for Option<T> {
|
impl<'r, T: FromData<'r>> FromData<'r> for Option<T> {
|
||||||
type Error = std::convert::Infallible;
|
type Error = T::Error;
|
||||||
|
|
||||||
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
|
async fn from_data(req: &'r Request<'_>, mut data: Data<'r>) -> Outcome<'r, Self> {
|
||||||
match T::from_data(req, data).await {
|
// Ask for at least one byte of data, if it's empty, there is no body.
|
||||||
Success(v) => Success(Some(v)),
|
if data.peek(1).await.is_empty() {
|
||||||
Error(..) | Forward(..) => Success(None),
|
Outcome::Success(None)
|
||||||
}
|
} else {
|
||||||
|
T::from_data(req, data).await.map(Some)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -814,24 +814,51 @@ impl<'v, K, V> FromForm<'v> for BTreeMap<K, V>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct OptionFormCtx<'v, T: FromForm<'v>> {
|
||||||
|
strict: bool,
|
||||||
|
has_field: bool,
|
||||||
|
inner: T::Context,
|
||||||
|
}
|
||||||
|
|
||||||
#[crate::async_trait]
|
#[crate::async_trait]
|
||||||
impl<'v, T: FromForm<'v>> FromForm<'v> for Option<T> {
|
impl<'v, T: FromForm<'v>> FromForm<'v> for Option<T> {
|
||||||
type Context = <T as FromForm<'v>>::Context;
|
type Context = OptionFormCtx<'v, T>;
|
||||||
|
|
||||||
fn init(_: Options) -> Self::Context {
|
fn init(opts: Options) -> Self::Context {
|
||||||
T::init(Options { strict: true })
|
OptionFormCtx {
|
||||||
|
strict: opts.strict,
|
||||||
|
has_field: false,
|
||||||
|
inner: T::init(Options { strict: true }),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
|
fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
|
||||||
T::push_value(ctxt, field)
|
ctxt.has_field = true;
|
||||||
|
T::push_value(&mut ctxt.inner, field)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
|
async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
|
||||||
T::push_data(ctxt, field).await
|
ctxt.has_field = true;
|
||||||
|
T::push_data(&mut ctxt.inner, field).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(this: Self::Context) -> Result<'v, Self> {
|
fn finalize(this: Self::Context) -> Result<'v, Self> {
|
||||||
Ok(T::finalize(this).ok())
|
if this.has_field {
|
||||||
|
match T::finalize(this.inner) {
|
||||||
|
Ok(v) => Ok(Some(v)),
|
||||||
|
Err(errors) => {
|
||||||
|
if this.strict ||
|
||||||
|
errors.iter().any(|e| e.kind != ErrorKind::Missing)
|
||||||
|
{
|
||||||
|
Err(errors)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -299,17 +299,17 @@ impl<'a, T: FromParam<'a>> FromParam<'a> for Result<T, T::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: FromParam<'a>> FromParam<'a> for Option<T> {
|
// impl<'a, T: FromParam<'a>> FromParam<'a> for Option<T> {
|
||||||
type Error = std::convert::Infallible;
|
// type Error = std::convert::Infallible;
|
||||||
|
|
||||||
#[inline]
|
// #[inline]
|
||||||
fn from_param(param: &'a str) -> Result<Self, Self::Error> {
|
// fn from_param(param: &'a str) -> Result<Self, Self::Error> {
|
||||||
match T::from_param(param) {
|
// match T::from_param(param) {
|
||||||
Ok(val) => Ok(Some(val)),
|
// Ok(val) => Ok(Some(val)),
|
||||||
Err(_) => Ok(None)
|
// Err(_) => Ok(None)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Trait to convert _many_ dynamic path segment strings to a concrete value.
|
/// Trait to convert _many_ dynamic path segment strings to a concrete value.
|
||||||
///
|
///
|
||||||
|
@ -384,13 +384,14 @@ impl<'r, T: FromSegments<'r>> FromSegments<'r> for Result<T, T::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r, T: FromSegments<'r>> FromSegments<'r> for Option<T> {
|
impl<'r, T: FromSegments<'r>> FromSegments<'r> for Option<T> {
|
||||||
type Error = std::convert::Infallible;
|
type Error = T::Error;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_segments(segments: Segments<'r, Path>) -> Result<Option<T>, Self::Error> {
|
fn from_segments(segments: Segments<'r, Path>) -> Result<Option<T>, Self::Error> {
|
||||||
match T::from_segments(segments) {
|
if segments.is_empty() {
|
||||||
Ok(val) => Ok(Some(val)),
|
Ok(None)
|
||||||
Err(_) => Ok(None)
|
} else {
|
||||||
|
T::from_segments(segments).map(Some)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue