litext 1.3.0

Seamless proc-macro literal extraction.
Documentation
use proc_macro2::Span;

/// A parsed string literal bundled with its source location.
///
/// Use `LitStr` instead of `String` when you need the span for diagnostics.
/// The [`value`](Self::value) field contains the unescaped content with escape
/// sequences resolved.
///
/// | Input | Extracted value |
/// |-------|-----------------|
/// | `"hello"` | `hello` |
/// | `"hello\nworld"` | `hello` + newline + `world` |
/// | `r#"hello\nworld"#` | `hello\nworld` (verbatim) |
/// | `"\x41"` | `A` |
/// | `"\u{1F600}"` | The emoji character |
///
/// # Supported Formats
///
/// - Regular strings: `"hello world"`
/// - Escape sequences: `"\n"`, `"\t"`, `"\\"`, `"\""`, `"\0"`, `"\x41"`, `"\u{1F600}"`
/// - Raw strings: `r#"no escapes here"#`, `r##"can contain #"##`
///
/// # Example
///
/// ```ignore
/// use litext::{litext, TokenStream};
/// use litext::literal::LitStr;
///
/// pub fn my_macro(input: TokenStream) -> TokenStream {
///     let lit = litext!(input as LitStr);
///
///     if lit.value().is_empty() {
///         return comperr::error(lit.span(), "string cannot be empty");
///     }
///
///     let text = lit.value();
///     // ... proceed with expansion
/// }
/// ```
///
/// # See Also
///
/// - [`FromLit`](super::FromLit) for the extraction trait
/// - [`ToTokens`](super::ToTokens) for converting back to a `TokenStream`
pub struct LitStr {
    /// The inner text of the string literal, with quotes and escape sequences removed.
    ///
    /// For a literal like `"hello\nworld"` this will be `hello` + newline + `world`.
    /// For a raw literal like `r#"hello\nworld"#` this will be `hello\nworld` verbatim,
    /// since raw strings do not process escape sequences.
    pub value: String,

    /// The source location of the string literal in the macro input.
    ///
    /// Useful for emitting compiler diagnostics that point at the exact position
    /// of the literal, for example via `Diagnostic::spanned` on nightly, or by
    /// constructing a new token with this span attached.
    pub span: Span,
}

impl LitStr {
    /// Creates a new `LitStr` from an unescaped value and its source span.
    ///
    /// This is typically called by the internal parsing logic after
    /// resolving escapes and identifying the literal's location.
    #[must_use]
    pub const fn new(value: String, span: Span) -> Self {
        Self { value, span }
    }

    /// Returns a reference to the unescaped string content.
    #[must_use]
    pub fn value(&self) -> &str {
        &self.value
    }

    /// Returns the source span of the literal.
    ///
    /// This span can be used with crates like `proc_macro2` or `syn` to
    /// anchor error messages to the specific string in the user's code.
    #[must_use]
    pub const fn span(&self) -> Span {
        self.span
    }
}