emf-core-base-rs 0.1.2

Idiomatic Rust wrapper of the emf-core-base interface
Documentation
//! Version api.
//!
//! The version api is exposed by the [VersionAPI] trait.
use crate::ffi::collections::{ConstSpan, MutSpan, NonNullConst};
use crate::ffi::version::api::VersionBinding;
use crate::ffi::Bool;
use std::cmp::Ordering;
use std::ptr::NonNull;

pub use crate::ffi::version::{Error, ReleaseType, Version};

/// Trait for providing access to the version api.
pub trait VersionAPI {
    /// Constructs a new version.
    ///
    /// Constructs a new version with `major`, `minor` and `patch` and sets the rest to `0`.
    ///
    /// # Return
    ///
    /// Constructed version.
    fn new_short(&self, major: i32, minor: i32, patch: i32) -> Version;

    /// Constructs a new version.
    ///
    /// Constructs a new version with `major`, `minor`, `patch`, `release_type` and
    /// `release_number` and sets the rest to `0`.
    ///
    /// # Return
    ///
    /// Constructed version.
    fn new_long(
        &self,
        major: i32,
        minor: i32,
        patch: i32,
        release_type: ReleaseType,
        release_number: i8,
    ) -> Version;

    /// Constructs a new version.
    ///
    /// Constructs a new version with `major`, `minor`, `patch`, `release_type`,
    /// `release_number` and `build`.
    ///
    /// # Return
    ///
    /// Constructed version.
    fn new_full(
        &self,
        major: i32,
        minor: i32,
        patch: i32,
        release_type: ReleaseType,
        release_number: i8,
        build: i64,
    ) -> Version;

    /// Constructs a version from a string.
    ///
    /// # Failure
    ///
    /// Fails if `string_is_valid(buffer) == false`.
    ///
    /// # Return
    ///
    /// Constructed version.
    fn from_string(&self, buffer: impl AsRef<str>) -> Result<Version, Error>;

    /// Computes the length of the short version string.
    ///
    /// # Return
    ///
    /// Length of the string.
    fn string_length_short(&self, version: &Version) -> usize;

    /// Computes the length of the long version string.
    ///
    /// # Return
    ///
    /// Length of the string.
    fn string_length_long(&self, version: &Version) -> usize;

    /// Computes the length of the full version string.
    ///
    /// # Return
    ///
    /// Length of the string.
    fn string_length_full(&self, version: &Version) -> usize;

    /// Represents the version as a short string.
    ///
    /// # Failure
    ///
    /// This function fails if `buffer.len() < string_length_short(version)`.
    ///
    /// # Return
    ///
    /// Number of written characters on success, error otherwise.
    fn as_string_short(&self, version: &Version, buffer: impl AsMut<str>) -> Result<usize, Error>;

    /// Represents the version as a long string.
    ///
    /// # Failure
    ///
    /// This function fails if `buffer.len() < string_length_long(version)`.
    ///
    /// # Return
    ///
    /// Number of written characters on success, error otherwise.
    fn as_string_long(&self, version: &Version, buffer: impl AsMut<str>) -> Result<usize, Error>;

    /// Represents the version as a full string.
    ///
    /// # Failure
    ///
    /// This function fails if `buffer.len() < string_length_full(version)`.
    ///
    /// # Return
    ///
    /// Number of written characters on success, error otherwise.
    fn as_string_full(&self, version: &Version, buffer: impl AsMut<str>) -> Result<usize, Error>;

    /// Checks whether the version string is valid.
    ///
    /// # Return
    ///
    /// [true] if the string is valid, [false] otherwise.
    fn string_is_valid(&self, version_string: impl AsRef<str>) -> bool;

    /// Compares two versions.
    ///
    /// Compares two version, disregarding their build number.
    ///
    /// # Return
    ///
    /// Order of the versions.
    fn compare(&self, lhs: &Version, rhs: &Version) -> Ordering;

    /// Compares two versions.
    ///
    /// Compares two version, disregarding their build number and release type.
    ///
    /// # Return
    ///
    /// Order of the versions.
    fn compare_weak(&self, lhs: &Version, rhs: &Version) -> Ordering;

    /// Compares two versions.
    ///
    /// # Return
    ///
    /// Order of the versions.
    fn compare_strong(&self, lhs: &Version, rhs: &Version) -> Ordering;

    /// Checks for compatibility of two versions.
    ///
    /// Two compatible versions can be used interchangeably.
    ///
    /// # Note
    ///
    /// This function is not commutative.
    ///
    /// # Return
    ///
    /// [true] if the versions are compatible, [false] otherwise.
    fn is_compatible(&self, lhs: &Version, rhs: &Version) -> bool;
}

impl<T> VersionAPI for T
where
    T: VersionBinding,
{
    #[inline]
    fn new_short(&self, major: i32, minor: i32, patch: i32) -> Version {
        unsafe { <T as VersionBinding>::new_short(self, major, minor, patch) }
    }

    #[inline]
    fn new_long(
        &self,
        major: i32,
        minor: i32,
        patch: i32,
        release_type: ReleaseType,
        release_number: i8,
    ) -> Version {
        unsafe {
            <T as VersionBinding>::new_long(self, major, minor, patch, release_type, release_number)
        }
    }

    #[inline]
    fn new_full(
        &self,
        major: i32,
        minor: i32,
        patch: i32,
        release_type: ReleaseType,
        release_number: i8,
        build: i64,
    ) -> Version {
        unsafe {
            <T as VersionBinding>::new_full(
                self,
                major,
                minor,
                patch,
                release_type,
                release_number,
                build,
            )
        }
    }

    #[inline]
    fn from_string(&self, buffer: impl AsRef<str>) -> Result<Version, Error> {
        unsafe {
            <T as VersionBinding>::from_string(
                self,
                NonNullConst::from(&ConstSpan::from(buffer.as_ref())),
            )
            .to_result()
        }
    }

    #[inline]
    fn string_length_short(&self, version: &Version) -> usize {
        unsafe { <T as VersionBinding>::string_length_short(self, NonNullConst::from(version)) }
    }

    #[inline]
    fn string_length_long(&self, version: &Version) -> usize {
        unsafe { <T as VersionBinding>::string_length_long(self, NonNullConst::from(version)) }
    }

    #[inline]
    fn string_length_full(&self, version: &Version) -> usize {
        unsafe { <T as VersionBinding>::string_length_full(self, NonNullConst::from(version)) }
    }

    #[inline]
    fn as_string_short(
        &self,
        version: &Version,
        mut buffer: impl AsMut<str>,
    ) -> Result<usize, Error> {
        unsafe {
            <T as VersionBinding>::as_string_short(
                self,
                NonNullConst::from(version),
                NonNull::from(&MutSpan::from(buffer.as_mut())),
            )
            .to_result()
        }
    }

    #[inline]
    fn as_string_long(
        &self,
        version: &Version,
        mut buffer: impl AsMut<str>,
    ) -> Result<usize, Error> {
        unsafe {
            <T as VersionBinding>::as_string_long(
                self,
                NonNullConst::from(version),
                NonNull::from(&MutSpan::from(buffer.as_mut())),
            )
            .to_result()
        }
    }

    #[inline]
    fn as_string_full(
        &self,
        version: &Version,
        mut buffer: impl AsMut<str>,
    ) -> Result<usize, Error> {
        unsafe {
            <T as VersionBinding>::as_string_full(
                self,
                NonNullConst::from(version),
                NonNull::from(&MutSpan::from(buffer.as_mut())),
            )
            .to_result()
        }
    }

    #[inline]
    fn string_is_valid(&self, version_string: impl AsRef<str>) -> bool {
        unsafe {
            <T as VersionBinding>::string_is_valid(
                self,
                NonNullConst::from(&ConstSpan::from(version_string.as_ref())),
            ) == Bool::True
        }
    }

    #[inline]
    fn compare(&self, lhs: &Version, rhs: &Version) -> Ordering {
        unsafe {
            match <T as VersionBinding>::compare(
                self,
                NonNullConst::from(lhs),
                NonNullConst::from(rhs),
            ) {
                -1 => Ordering::Greater,
                0 => Ordering::Equal,
                1 => Ordering::Less,
                _ => unreachable!(),
            }
        }
    }

    #[inline]
    fn compare_weak(&self, lhs: &Version, rhs: &Version) -> Ordering {
        unsafe {
            match <T as VersionBinding>::compare_weak(
                self,
                NonNullConst::from(lhs),
                NonNullConst::from(rhs),
            ) {
                -1 => Ordering::Greater,
                0 => Ordering::Equal,
                1 => Ordering::Less,
                _ => unreachable!(),
            }
        }
    }

    #[inline]
    fn compare_strong(&self, lhs: &Version, rhs: &Version) -> Ordering {
        unsafe {
            match <T as VersionBinding>::compare_strong(
                self,
                NonNullConst::from(lhs),
                NonNullConst::from(rhs),
            ) {
                -1 => Ordering::Greater,
                0 => Ordering::Equal,
                1 => Ordering::Less,
                _ => unreachable!(),
            }
        }
    }

    #[inline]
    fn is_compatible(&self, lhs: &Version, rhs: &Version) -> bool {
        unsafe {
            <T as VersionBinding>::is_compatible(
                self,
                NonNullConst::from(lhs),
                NonNullConst::from(rhs),
            ) == Bool::True
        }
    }
}