Skip to content

Commit 872595b

Browse files
the10thWizSergioBenitez
authored andcommitted
Change meaning of Option
1 parent 1f82d4b commit 872595b

File tree

3 files changed

+57
-27
lines changed

3 files changed

+57
-27
lines changed

core/lib/src/data/from_data.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,14 @@ impl<'r, T: FromData<'r> + 'r> FromData<'r> for Result<T, T::Error> {
415415

416416
#[crate::async_trait]
417417
impl<'r, T: FromData<'r>> FromData<'r> for Option<T> {
418-
type Error = std::convert::Infallible;
418+
type Error = T::Error;
419419

420-
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
421-
match T::from_data(req, data).await {
422-
Success(v) => Success(Some(v)),
423-
Error(..) | Forward(..) => Success(None),
424-
}
420+
async fn from_data(req: &'r Request<'_>, mut data: Data<'r>) -> Outcome<'r, Self> {
421+
// Ask for at least one byte of data, if it's empty, there is no body.
422+
if data.peek(1).await.is_empty() {
423+
Outcome::Success(None)
424+
} else {
425+
T::from_data(req, data).await.map(Some)
426+
}
425427
}
426428
}

core/lib/src/form/from_form.rs

+33-6
Original file line numberDiff line numberDiff line change
@@ -814,24 +814,51 @@ impl<'v, K, V> FromForm<'v> for BTreeMap<K, V>
814814
}
815815
}
816816

817+
struct OptionFormCtx<'v, T: FromForm<'v>> {
818+
strict: bool,
819+
has_field: bool,
820+
inner: T::Context,
821+
}
822+
817823
#[crate::async_trait]
818824
impl<'v, T: FromForm<'v>> FromForm<'v> for Option<T> {
819-
type Context = <T as FromForm<'v>>::Context;
825+
type Context = OptionFormCtx<'v, T>;
820826

821-
fn init(_: Options) -> Self::Context {
822-
T::init(Options { strict: true })
827+
fn init(opts: Options) -> Self::Context {
828+
OptionFormCtx {
829+
strict: opts.strict,
830+
has_field: false,
831+
inner: T::init(Options { strict: true }),
832+
}
823833
}
824834

825835
fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {
826-
T::push_value(ctxt, field)
836+
ctxt.has_field = true;
837+
T::push_value(&mut ctxt.inner, field)
827838
}
828839

829840
async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {
830-
T::push_data(ctxt, field).await
841+
ctxt.has_field = true;
842+
T::push_data(&mut ctxt.inner, field).await
831843
}
832844

833845
fn finalize(this: Self::Context) -> Result<'v, Self> {
834-
Ok(T::finalize(this).ok())
846+
if this.has_field {
847+
match T::finalize(this.inner) {
848+
Ok(v) => Ok(Some(v)),
849+
Err(errors) => {
850+
if this.strict ||
851+
errors.iter().any(|e| e.kind != ErrorKind::Missing)
852+
{
853+
Err(errors)
854+
} else {
855+
Ok(None)
856+
}
857+
}
858+
}
859+
} else {
860+
Ok(None)
861+
}
835862
}
836863
}
837864

core/lib/src/request/from_param.rs

+16-15
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,17 @@ impl<'a, T: FromParam<'a>> FromParam<'a> for Result<T, T::Error> {
299299
}
300300
}
301301

302-
impl<'a, T: FromParam<'a>> FromParam<'a> for Option<T> {
303-
type Error = std::convert::Infallible;
304-
305-
#[inline]
306-
fn from_param(param: &'a str) -> Result<Self, Self::Error> {
307-
match T::from_param(param) {
308-
Ok(val) => Ok(Some(val)),
309-
Err(_) => Ok(None)
310-
}
311-
}
312-
}
302+
// impl<'a, T: FromParam<'a>> FromParam<'a> for Option<T> {
303+
// type Error = std::convert::Infallible;
304+
305+
// #[inline]
306+
// fn from_param(param: &'a str) -> Result<Self, Self::Error> {
307+
// match T::from_param(param) {
308+
// Ok(val) => Ok(Some(val)),
309+
// Err(_) => Ok(None)
310+
// }
311+
// }
312+
// }
313313

314314
/// Trait to convert _many_ dynamic path segment strings to a concrete value.
315315
///
@@ -384,13 +384,14 @@ impl<'r, T: FromSegments<'r>> FromSegments<'r> for Result<T, T::Error> {
384384
}
385385

386386
impl<'r, T: FromSegments<'r>> FromSegments<'r> for Option<T> {
387-
type Error = std::convert::Infallible;
387+
type Error = T::Error;
388388

389389
#[inline]
390390
fn from_segments(segments: Segments<'r, Path>) -> Result<Option<T>, Self::Error> {
391-
match T::from_segments(segments) {
392-
Ok(val) => Ok(Some(val)),
393-
Err(_) => Ok(None)
391+
if segments.is_empty() {
392+
Ok(None)
393+
} else {
394+
T::from_segments(segments).map(Some)
394395
}
395396
}
396397
}

0 commit comments

Comments
 (0)