libgraphql-macros 0.0.10

Macros provided by the `libgraphql` crate at `libgraphql::macros`.
Documentation
use proc_macro2::Span;
use std::collections::HashMap;

/// Maps synthetic byte offsets back to `proc_macro2::Span`s.
///
/// The keys are synthetic `u32` values generated by
/// `RustMacroGraphQLTokenSource` as it emits tokens. These don't
/// correspond to real file byte positions — they are monotonically
/// increasing unique identifiers that allow mapping `ByteSpan.start`
/// values from parse errors back to the original `proc_macro2::Span`
/// for accurate `compile_error!` placement.
///
/// We use synthetic offsets rather than real byte offsets because
/// `proc_macro2::Span::byte_range()` only returns meaningful values
/// on nightly Rust toolchains. On stable toolchains, byte offsets are
/// unreliable/zeroed. Synthetic offsets work on all toolchains.
pub(crate) struct SpanMap(HashMap<u32, Span>);

impl SpanMap {
    pub fn new(map: HashMap<u32, Span>) -> Self {
        Self(map)
    }

    /// Looks up the `proc_macro2::Span` for a given synthetic byte
    /// offset (typically `ByteSpan.start` from a parse error).
    ///
    /// Returns `None` if no exact match is found. This is
    /// unexpected at runtime — error positions should always
    /// correspond to token start positions recorded during
    /// tokenization. If `None` is returned, the caller should
    /// fall back to `Span::call_site()` and consider emitting a
    /// diagnostic asking the user to report the issue on GitHub.
    pub fn lookup_byte_offset(&self, byte_offset: u32) -> Option<Span> {
        self.0.get(&byte_offset).copied()
    }
}