use std::marker::PhantomData; use std::ops::{BitAnd, BitOr}; use typenum::{Cmp, IsEqual, IsLess, IsLessOrEqual, Unsigned}; /// This trait represents a version at compile time trait Version{ type Major: Unsigned; type Minor: Unsigned; } /// This struct contains nothing and is used to represent specific versions as an instance of /// [`Version`]. It is instances as `Ver` struct Ver{ _phantom: PhantomData<(MAJ, MIN)> } impl Version for Ver{ type Major = MAJ; type Minor = MIN; } /// Represents two versions which can be compared trait ComparableVersion: Version{ type IsAtLeast: SameOrUnit; } impl ComparableVersion for U where ::Major: Cmp, ::Minor: IsLessOrEqual, ::Major: IsEqual< Self::Major, Output: BitAnd< typenum::LeEq >, >, ::Major: IsLess< Self::Major, Output: BitOr< typenum::And< typenum::Eq, typenum::LeEq, >, Output: SameOrUnit > > { type IsAtLeast = typenum::Or< typenum::Le, typenum::And< typenum::Eq, typenum::LeEq, > >; } /// Simple check for testing if the `TEST` version is at least `REQ` or higher. type VersionAbove = >::IsAtLeast; trait VersionIsAtLeast{} impl> VersionIsAtLeast for T{} /// Trait for containing the result of elements which only conditionally exist trait CondElemResult{ type Output; } /// Empty helper struct which only servers to give a concrete type when creating fields in rmc /// structs which have a version requirement. This is not meant to be used directly, use /// [`MinVersion`] instead. struct MinVersionElementHelper>{ _phantom: PhantomData<(T, REQUIRED, VER)> } /// This should be used either with [`typenum::True`] or [`typenum::False`]. When `True` the [`Self::Output`] /// will be the same as the `T` you put into Output. When `False` it will always be `()` trait SameOrUnit{ type Output; } impl SameOrUnit for typenum::True{ type Output = T; } impl SameOrUnit for typenum::False{ type Output = (); } impl> CondElemResult for MinVersionElementHelper where { type Output = <>::IsAtLeast as SameOrUnit>::Output; } /// When the version condition is met the field will exist and will simply be `T` if not it will be /// replaced by `()`. Use this when you need to add versioning to rmc structs. type MinVersion = as CondElemResult>::Output;