diff --git a/src/entity/active_value.rs b/src/entity/active_value.rs index 315fcbeb6..6465244e1 100644 --- a/src/entity/active_value.rs +++ b/src/entity/active_value.rs @@ -413,6 +413,80 @@ where ActiveValue::NotSet => None, } } + + /// Flattens `&ActiveValue>` into an `Option<&T>`, folding [NotSet][ActiveValue::NotSet] + /// and [None][Option::None] together, and [Set][ActiveValue::Set], [Unchanged][ActiveValue::Unchanged], + /// and [Some][Option::Some] together. This can replace `model.field.try_as_ref().and_then(Option::as_ref)`. + /// + /// For a version on owned [ActiveValue]s, see [ActiveValue::flatten]. + /// + /// ``` + /// use sea_orm::ActiveValue; + /// + /// let x: &ActiveValue> = &ActiveValue::Set(Some(0)); + /// let y: &ActiveValue> = &ActiveValue::Set(None); + /// let z: &ActiveValue> = &ActiveValue::NotSet; + /// + /// assert_eq!(x.flatten_ref(), Some(&0)); + /// assert_eq!(y.flatten_ref(), None); + /// assert_eq!(z.flatten_ref(), None); + /// ``` + pub fn flatten_ref<'a, T>(&self) -> Option<&'a T> + where V: AsRefOption<'a, T> { + match self { + ActiveValue::Set(value) | ActiveValue::Unchanged(value) => value.as_ref_opt().as_ref(), + ActiveValue::NotSet => None, + } + } + + /// Flattens `ActiveValue>` into an `Option`, folding [NotSet][ActiveValue::NotSet] + /// and [None][Option::None] together, and [Set][ActiveValue::Set], [Unchanged][ActiveValue::Unchanged], + /// and [Some][Option::Some] together. This can replace `model.field.take().flatten()`. + /// + /// For a version on owned [ActiveValue]s, see [ActiveValue::flatten]. + /// + /// ``` + /// use sea_orm::ActiveValue; + /// + /// let x: ActiveValue> = ActiveValue::Set(Some(0)); + /// let y: ActiveValue> = ActiveValue::Set(None); + /// let z: ActiveValue> = ActiveValue::NotSet; + /// + /// assert_eq!(x.flatten(), Some(0)); + /// assert_eq!(y.flatten(), None); + /// assert_eq!(z.flatten(), None); + /// ``` + pub fn flatten<'a, T>(&self) -> Option + where V: AsOwnedOption { + match self { + ActiveValue::Set(value) | ActiveValue::Unchanged(value) => value.as_opt(), + ActiveValue::NotSet => None, + } + } +} + +mod private { + pub trait RefOptSealed {} + pub trait OwnedOptSealed {} +} +pub trait AsRefOption<'a, T>: private::RefOptSealed { + fn as_ref_opt(self) -> &'a Option; +} +impl<'a, T> private::RefOptSealed for &'a Option {} +impl<'a, T> AsRefOption for &'a Option { + fn as_ref_opt(self) -> &'a Option { + self + } +} + +pub trait AsOwnedOption: OwnedOptSealed { + fn as_opt(self) -> Option; +} +impl private::OwnedOptSealed for Option {} +impl AsOwnedOption for Option { + fn as_opt(self) -> Option { + self + } } impl std::convert::AsRef for ActiveValue