Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Impressum features.rs   Sprache: unbekannt

 
//! Contains code for selecting features

#![deny(unused_extern_crates)]
#![deny(clippy::missing_docs_in_private_items)]
#![allow(deprecated)]

use std::cmp::Ordering;
use std::io;
use std::str::FromStr;

/// This macro defines the [`RustTarget`] and [`RustFeatures`] types.
macro_rules! define_rust_targets {
    (
        Nightly => {$($nightly_feature:ident $(: #$issue:literal)?),* $(,)?} $(,)?
        $(
            $(#[$attrs:meta])*
            $variant:ident($minor:literal) => {$($feature:ident $(: #$pull:literal)?),* $(,)?},
        )*
        $(,)?
    ) => {
        /// Represents the version of the Rust language to target.
        ///
        /// To support a beta release, use the corresponding stable release.
        ///
        /// This enum will have more variants added as necessary.
        #[allow(non_camel_case_types)]
        #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
        pub enum RustTarget {
            /// Rust Nightly
            $(#[doc = concat!(
                "- [`", stringify!($nightly_feature), "`]",
                "(", $("https://github.com/rust-lang/rust/pull/", stringify!($issue),)* ")",
            )])*
            Nightly,
            $(
                #[doc = concat!("Rust 1.", stringify!($minor))]
                $(#[doc = concat!(
                    "- [`", stringify!($feature), "`]",
                    "(", $("https://github.com/rust-lang/rust/pull/", stringify!($pull),)* ")",
                )])*
                $(#[$attrs])*
                $variant,
            )*
        }

        impl RustTarget {
            fn minor(self) -> Option<u64> {
                match self {
                    $( Self::$variant => Some($minor),)*
                    Self::Nightly => None
                }
            }

            const fn stable_releases() -> [(Self, u64); [$($minor,)*].len()] {
                [$((Self::$variant, $minor),)*]
            }
        }

        #[cfg(feature = "__cli")]
        /// Strings of allowed `RustTarget` values
        pub const RUST_TARGET_STRINGS: &[&str] = &[$(concat!("1.", stringify!($minor)),)*];

        #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
        pub(crate) struct RustFeatures {
            $($(pub(crate) $feature: bool,)*)*
            $(pub(crate) $nightly_feature: bool,)*
        }

        impl From<RustTarget> for RustFeatures {
            fn from(target: RustTarget) -> Self {
                if target == RustTarget::Nightly {
                    return Self {
                        $($($feature: true,)*)*
                        $($nightly_feature: true,)*
                    };
                }

                let mut features = Self {
                    $($($feature: false,)*)*
                    $($nightly_feature: false,)*
                };

                $(if target >= RustTarget::$variant {
                    $(features.$feature = true;)*
                })*

                features
            }
        }
    };
}

// NOTE: When adding or removing features here, make sure to add the stabilization PR
// number for the feature if it has been stabilized or the tracking issue number if the feature is
// not stable.
define_rust_targets! {
    Nightly => {
        vectorcall_abi,
    },
    Stable_1_73(73) => { thiscall_abi: #42202 },
    Stable_1_71(71) => { c_unwind_abi: #106075 },
    Stable_1_68(68) => { abi_efiapi: #105795 },
    Stable_1_64(64) => { core_ffi_c: #94503 },
    Stable_1_59(59) => { const_cstr: #54745 },
    Stable_1_47(47) => { larger_arrays: #74060 },
    Stable_1_40(40) => { non_exhaustive: #44109 },
    Stable_1_36(36) => { maybe_uninit: #60445 },
    Stable_1_33(33) => { repr_packed_n: #57049 },
    #[deprecated]
    Stable_1_30(30) => {
        core_ffi_c_void: #53910,
        min_const_fn: #54835,
    },
    #[deprecated]
    Stable_1_28(28) => { repr_transparent: #51562 },
    #[deprecated]
    Stable_1_27(27) => { must_use_function: #48925 },
    #[deprecated]
    Stable_1_26(26) => { i128_and_u128: #49101 },
    #[deprecated]
    Stable_1_25(25) => { repr_align: #47006 },
    #[deprecated]
    Stable_1_21(21) => { builtin_clone_impls: #43690 },
    #[deprecated]
    Stable_1_20(20) => { associated_const: #42809 },
    #[deprecated]
    Stable_1_19(19) => { untagged_union: #42068 },
    #[deprecated]
    Stable_1_17(17) => { static_lifetime_elision: #39265 },
    #[deprecated]
    Stable_1_0(0) => {},
}

/// Latest stable release of Rust
pub const LATEST_STABLE_RUST: RustTarget = {
    // FIXME: replace all this code by
    // ```
    // RustTarget::stable_releases()
    //     .into_iter()
    //     .max_by_key(|(_, m)| m)
    //     .map(|(t, _)| t)
    //     .unwrap_or(RustTarget::Nightly)
    // ```
    // once those operations can be used in constants.
    let targets = RustTarget::stable_releases();

    let mut i = 0;
    let mut latest_target = None;
    let mut latest_minor = 0;

    while i < targets.len() {
        let (target, minor) = targets[i];

        if latest_minor < minor {
            latest_minor = minor;
            latest_target = Some(target);
        }

        i += 1;
    }

    match latest_target {
        Some(target) => target,
        None => unreachable!(),
    }
};

impl Default for RustTarget {
    fn default() -> Self {
        LATEST_STABLE_RUST
    }
}

impl PartialOrd for RustTarget {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for RustTarget {
    fn cmp(&self, other: &Self) -> Ordering {
        match (self.minor(), other.minor()) {
            (Some(a), Some(b)) => a.cmp(&b),
            (Some(_), None) => Ordering::Less,
            (None, Some(_)) => Ordering::Greater,
            (None, None) => Ordering::Equal,
        }
    }
}

impl FromStr for RustTarget {
    type Err = io::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s == "nightly" {
            return Ok(Self::Nightly);
        }

        if let Some(("1", str_minor)) = s.split_once('.') {
            if let Ok(minor) = str_minor.parse::<u64>() {
                for (target, target_minor) in Self::stable_releases() {
                    if minor == target_minor {
                        return Ok(target);
                    }
                }
            }
        }

        Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Got an invalid Rust target. Accepted values are of the form \"1.71\" or \"nightly\"."
        ))
    }
}

impl std::fmt::Display for RustTarget {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self.minor() {
            Some(minor) => write!(f, "1.{}", minor),
            None => "nightly".fmt(f),
        }
    }
}

impl Default for RustFeatures {
    fn default() -> Self {
        RustTarget::default().into()
    }
}

#[cfg(test)]
mod test {
    #![allow(unused_imports)]
    use super::*;

    #[test]
    fn target_features() {
        let f_1_0 = RustFeatures::from(RustTarget::Stable_1_0);
        assert!(
            !f_1_0.static_lifetime_elision &&
                !f_1_0.core_ffi_c_void &&
                !f_1_0.untagged_union &&
                !f_1_0.associated_const &&
                !f_1_0.builtin_clone_impls &&
                !f_1_0.repr_align &&
                !f_1_0.thiscall_abi &&
                !f_1_0.vectorcall_abi
        );
        let f_1_21 = RustFeatures::from(RustTarget::Stable_1_21);
        assert!(
            f_1_21.static_lifetime_elision &&
                !f_1_21.core_ffi_c_void &&
                f_1_21.untagged_union &&
                f_1_21.associated_const &&
                f_1_21.builtin_clone_impls &&
                !f_1_21.repr_align &&
                !f_1_21.thiscall_abi &&
                !f_1_21.vectorcall_abi
        );
        let features = RustFeatures::from(RustTarget::Stable_1_71);
        assert!(
            features.c_unwind_abi &&
                features.abi_efiapi &&
                !features.thiscall_abi
        );
        let f_nightly = RustFeatures::from(RustTarget::Nightly);
        assert!(
            f_nightly.static_lifetime_elision &&
                f_nightly.core_ffi_c_void &&
                f_nightly.untagged_union &&
                f_nightly.associated_const &&
                f_nightly.builtin_clone_impls &&
                f_nightly.maybe_uninit &&
                f_nightly.repr_align &&
                f_nightly.thiscall_abi &&
                f_nightly.vectorcall_abi
        );
    }

    fn test_target(target_str: &str, target: RustTarget) {
        let target_string = target.to_string();
        assert_eq!(target_str, target_string);
        assert_eq!(target, RustTarget::from_str(target_str).unwrap());
    }

    #[test]
    fn str_to_target() {
        test_target("1.0", RustTarget::Stable_1_0);
        test_target("1.17", RustTarget::Stable_1_17);
        test_target("1.19", RustTarget::Stable_1_19);
        test_target("1.21", RustTarget::Stable_1_21);
        test_target("1.25", RustTarget::Stable_1_25);
        test_target("1.71", RustTarget::Stable_1_71);
        test_target("nightly", RustTarget::Nightly);
    }
}

[ Seitenstruktur0.26Drucken  etwas mehr zur Ethik  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge