Repository: paritytech/substrate
File: primitives/runtime/src/traits.rs (Rust)

Code before:
		r.checked_sub(&N::get()).unwrap_or(Zero::zero())
	} where N::Type: CheckedSub | Zero;

	/// A `TryMorph` implementation to reduce a scalar by a particular amount, checking for
	/// underflow.
	pub type CheckedReduceBy<N: TypedGet>: TryMorph = |r: N::Type| -> Result<N::Type, ()> {
		r.checked_sub(&N::get()).ok_or(())
	} where N::Type: CheckedSub;

	/// A `TryMorph` implementation to enforce an upper limit for a result of the outer morphed type.
	pub type MorphWithUpperLimit<L: TypedGet, M>: TryMorph = |r: L::Type| -> Result<L::Type, ()> {
		M::try_morph(r).map(|m| m.min(L::get()))
	} where L::Type: Ord, M: TryMorph<L::Type, Outcome = L::Type>;
}

/// Infallible conversion trait. Generic over both source and destination types.
pub trait Convert<A, B> {
	/// Make conversion.
	fn convert(a: A) -> B;
}

/// Fallible conversion trait returning a Result. Generic over both source and destination types.
///
/// In case an `Error` is returned, it must always be the operand which is returned.
pub trait TryConvert<A, B> {
	/// Attempt the conversion and return the input value in the error case.
	fn try_convert(a: A) -> Result<B, A>;
}

/// Reversing infallible conversion trait. Generic over both source and destination types.
///
/// This specifically reverses the conversion.
pub trait ConvertBack<A, B>: Convert<A, B> {
	/// Make conversion back.
	fn convert_back(b: B) -> A;
}

/// Fallible conversion trait returning a Result. Generic over both source and destination types.
///
/// In case an `Error` is returned, it must always be the operand which is returned.
pub trait TryConvertBack<A, B>: TryConvert<A, B> {
	/// Attempt to reverse the conversion and return the input value in the error case.
	fn try_convert_back(b: B) -> Result<A, B>;
}

impl<A, B: Default> Convert<A, B> for () {
	fn convert(_: A) -> B {
		Default::default()
	}
}


Review comment (suggestion):
```suggestion
}

impl<A, B, T: Convert<A, B>> TryConvert<A, B> for T {
    fn try_convert(a: A) -> Result<B, A> {
        Ok(T::convert(a))
    }
}
```

Code after:
		r.checked_sub(&N::get()).unwrap_or(Zero::zero())
	} where N::Type: CheckedSub | Zero;

	/// A `TryMorph` implementation to reduce a scalar by a particular amount, checking for
	/// underflow.
	pub type CheckedReduceBy<N: TypedGet>: TryMorph = |r: N::Type| -> Result<N::Type, ()> {
		r.checked_sub(&N::get()).ok_or(())
	} where N::Type: CheckedSub;

	/// A `TryMorph` implementation to enforce an upper limit for a result of the outer morphed type.
	pub type MorphWithUpperLimit<L: TypedGet, M>: TryMorph = |r: L::Type| -> Result<L::Type, ()> {
		M::try_morph(r).map(|m| m.min(L::get()))
	} where L::Type: Ord, M: TryMorph<L::Type, Outcome = L::Type>;
}

/// Infallible conversion trait. Generic over both source and destination types.
pub trait Convert<A, B> {
	/// Make conversion.
	fn convert(a: A) -> B;
}

impl<A, B: Default> Convert<A, B> for () {
	fn convert(_: A) -> B {
		Default::default()
	}
}

/// Reversing infallible conversion trait. Generic over both source and destination types.
///
/// This specifically reverses the conversion.
pub trait ConvertBack<A, B>: Convert<A, B> {
	/// Make conversion back.
	fn convert_back(b: B) -> A;
}

/// Fallible conversion trait returning an [Option]. Generic over both source and destination types.
pub trait MaybeConvert<A, B> {
	/// Attempt to make conversion.
	fn maybe_convert(a: A) -> Option<B>;
}

#[impl_trait_for_tuples::impl_for_tuples(30)]
impl<A: Clone, B> MaybeConvert<A, B> for Tuple {
	fn maybe_convert(a: A) -> Option<B> {
		for_tuples!( #(
			match Tuple::maybe_convert(a.clone()) {
				Some(b) => return Some(b),
				None => {},
			}
		)* );
		None