use super::*; /// A value that can be automatically determined. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum Smart { /// The value should be determined smartly based on the circumstances. Auto, /// A specific value. Custom(T), } impl Smart { /// Whether the value is `Auto`. pub fn is_auto(&self) -> bool { matches!(self, Self::Auto) } /// Whether this holds a custom value. pub fn is_custom(&self) -> bool { matches!(self, Self::Custom(_)) } /// Returns a reference the contained custom value. /// If the value is [`Smart::Auto`], `None` is returned. pub fn as_custom(self) -> Option { match self { Self::Auto => None, Self::Custom(x) => Some(x), } } /// Map the contained custom value with `f`. pub fn map(self, f: F) -> Smart where F: FnOnce(T) -> U, { match self { Self::Auto => Smart::Auto, Self::Custom(x) => Smart::Custom(f(x)), } } /// Map the contained custom value with `f` if it contains a custom value, /// otherwise returns `default`. pub fn map_or(self, default: U, f: F) -> U where F: FnOnce(T) -> U, { match self { Self::Auto => default, Self::Custom(x) => f(x), } } /// Keeps `self` if it contains a custom value, otherwise returns `other`. pub fn or(self, other: Smart) -> Self { match self { Self::Custom(x) => Self::Custom(x), Self::Auto => other, } } /// Returns the contained custom value or a provided default value. pub fn unwrap_or(self, default: T) -> T { match self { Self::Auto => default, Self::Custom(x) => x, } } /// Returns the contained custom value or computes a default value. pub fn unwrap_or_else(self, f: F) -> T where F: FnOnce() -> T, { match self { Self::Auto => f(), Self::Custom(x) => x, } } /// Returns the contained custom value or the default value. pub fn unwrap_or_default(self) -> T where T: Default, { self.unwrap_or_else(T::default) } } impl Default for Smart { fn default() -> Self { Self::Auto } } impl Cast for Smart { fn is(value: &Value) -> bool { matches!(value, Value::Auto) || T::is(value) } fn cast(value: Value) -> StrResult { match value { Value::Auto => Ok(Self::Auto), v if T::is(&v) => Ok(Self::Custom(T::cast(v)?)), _ => ::error(value), } } fn describe() -> CastInfo { T::describe() + CastInfo::Type("auto") } } impl Resolve for Smart { type Output = Smart; fn resolve(self, styles: StyleChain) -> Self::Output { self.map(|v| v.resolve(styles)) } } impl Fold for Smart where T: Fold, T::Output: Default, { type Output = Smart; fn fold(self, outer: Self::Output) -> Self::Output { self.map(|inner| inner.fold(outer.unwrap_or_default())) } } impl> From> for Value { fn from(v: Smart) -> Self { match v { Smart::Custom(v) => v.into(), Smart::Auto => Value::Auto, } } }