Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/third_party/rust/strck_ident/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 4 kB image not shown  

Quelle  rust.rs   Sprache: unbekannt

 
//! Checked strings containing Rust identifiers.
//!
//! Raw identifiers are unsupported.
//!
//! # Examples
//!
//! ```rust
//! use strck_ident::{IntoCk, rust::RustIdent};
//!
//! assert!("foo".ck::<RustIdent>().is_ok());
//! assert!("_identifier".ck::<RustIdent>().is_ok());
//! assert!("Москва".ck::<RustIdent>().is_ok());
//! assert!("東京".ck::<RustIdent>().is_ok());
//!
//! assert!("struct".ck::<RustIdent>().is_err());
//! assert!("r#try".ck::<RustIdent>().is_err());
//! assert!("��".ck::<RustIdent>().is_err());
//! ```
//!
//! # Aliases
//!
//! This module exposes [`Ident`] and [`IdentBuf`], which alias `Ck<RustIdent>`
//! and `Check<RustIdent>` respectively. These aliases are preferred to keep
//! type signatures succinct.
//!
//! # Requirements
//!
//! This module is only available when the `rust` feature flag is enabled.
use crate::unicode;
use core::fmt;
use strck::{Check, Ck, Invariant};

/// An [`Invariant`] for Rust identifiers.
///
/// Raw identifiers are unsupported.
///
/// # Invariants
///
/// * The string is nonempty.
/// * The first character is `_` or XID_Start.
/// * Any following characters are XID_Continue.
/// * The string isn't a single underscore, e.g. `"_"`.
/// * The string isn't a [strict] or [reserved] keyword.
///
/// [strict]: https://doc.rust-lang.org/reference/keywords.html#strict-keywords
/// [reserved]: https://doc.rust-lang.org/reference/keywords.html#reserved-keywords
#[derive(Clone, Debug)]
pub struct RustIdent;

/// Borrowed checked string containing a Rust identifier.
///
/// See [`RustIdent`] for more details.
pub type Ident = Ck<RustIdent>;

/// Owned checked string containing a Rust identifier.
///
/// See [`RustIdent`] for more details.
pub type IdentBuf<B = String> = Check<RustIdent, B>;

/// The error type returned from checking the invariants of [`RustIdent`].
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Error {
    /// An invalid unicode identifier.
    Unicode(unicode::Error),

    /// A [strict] or [reserved] keyword.
    ///
    /// [strict]: https://doc.rust-lang.org/reference/keywords.html#strict-keywords
    /// [reserved]: https://doc.rust-lang.org/reference/keywords.html#reserved-keywords
    Keyword(&'static str),

    /// A single underscore.
    Wildcard,
}

impl std::error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Unicode(err) => err.fmt(f),
            Error::Keyword(keyword) => {
                write!(f, "Rust keyword: '{keyword}'")
            }
            Error::Wildcard => f.pad("wildcard '_' isn't a valid Rust ident"),
        }
    }
}

impl Invariant for RustIdent {
    type Error = Error;

    fn check(slice: &str) -> Result<(), Self::Error> {
        match unicode::UnicodeIdent::check(slice) {
            Ok(()) => match KEYWORDS.binary_search(&slice) {
                Ok(index) => Err(Error::Keyword(KEYWORDS[index])),
                Err(_) => Ok(()),
            },
            Err(unicode::Error::Start('_')) => match slice.len() {
                1 => Err(Error::Wildcard), // `_` isn't ok
                _ => Ok(()),               // `_x` is ok
            },
            Err(e) => Err(Error::Unicode(e)),
        }
    }
}

static KEYWORDS: [&str; 51] = [
    "Self", "abstract", "as", "async", "await", "become", "box", "break", "const", "continue",
    "crate", "do", "dyn", "else", "enum", "extern", "false", "final", "fn", "for", "if", "impl",
    "in", "let", "loop", "macro", "match", "mod", "move", "mut", "override", "priv", "pub", "ref",
    "return", "self", "static", "struct", "super", "trait", "true", "try", "type", "typeof",
    "unsafe", "unsized", "use", "virtual", "where", "while", "yield",
];

#[cfg(test)]
mod tests {
    use super::{Error, RustIdent};
    use strck::IntoCk;

    #[test]
    fn test_underscore() {
        assert_eq!("_".ck::<RustIdent>().unwrap_err(), Error::Wildcard);
        assert!("_unused".ck::<RustIdent>().is_ok());
        assert!("__private".ck::<RustIdent>().is_ok());
        assert!("snake_case".ck::<RustIdent>().is_ok());
    }

    #[test]
    fn test_rust_reference() {
        assert!("foo".ck::<RustIdent>().is_ok());
        assert!("_identifier".ck::<RustIdent>().is_ok());
        assert!("Москва".ck::<RustIdent>().is_ok());
        assert!("東京".ck::<RustIdent>().is_ok());
    }
}

[ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ]