Skip to main content

Ruler

Struct Ruler 

Source
pub struct Ruler<'a> { /* private fields */ }
Expand description

Converts between scales for one specific text.

A Ruler cannot be built without the text, which is the structural reason a scale conversion can never be done “in general”: there is no such thing. "héllo".len() is 6 bytes and 5 chars, and only the string knows.

Implementations§

Source§

impl<'a> Ruler<'a>

Source

pub const fn new(text: &'a str) -> Ruler<'a>

Source

pub const fn end_bytes(&self) -> Offset<Bytes>

The text’s end, in bytes.

Source

pub fn end_chars(&self) -> Offset<Chars>

The text’s end, in chars.

Source

pub fn snap(&self, at: Offset<Bytes>) -> Offset<Bytes>

Clamp into the text and snap DOWN to a character boundary.

Snapping down, not up, keeps the result inside the character the offset pointed at — where an editor should underline. Mid-codepoint offsets are a NORMAL arrival, not corruption: they come from parser error spans over a buffer the user is halfway through typing a character into. Measured 2026-08-01: analyse("🔥🔥🔥") aborted on exactly this at offset 1.

Source

pub fn to_chars(&self, at: Offset<Bytes>) -> Offset<Chars>

Bytes → chars. Total: out-of-range and mid-codepoint inputs snap first.

Source

pub fn to_bytes(&self, at: Offset<Chars>) -> Offset<Bytes>

Chars → bytes. Total: past-the-end saturates to the text’s end.

Source

pub fn to_utf16(&self, at: Offset<Bytes>) -> Offset<Utf16Units>

Bytes → UTF-16 code units, for LSP.

Separate from Self::to_chars because they differ, and the difference is invisible until a user types an emoji: 🔥 is ONE char and TWO UTF-16 units. Conflating them shifts every position after it.

Source§

impl<'a> Ruler<'a>

Source

pub const fn ascending(&self) -> AscendingScan<'a>

A forward-only reader for offsets visited in ASCENDING order.

Ruler::to_chars is O(n) per call — text[..b].chars().count() re-walks from the start every time — because it must be TOTAL and random-access. That is right for a caret, and wrong for converting every match in a document: O(n) per call over m matches is O(n·m), which is the cost escriba-search originally avoided by building a dense usize-per-byte map.

This is the third option, better than both: O(n + m) total with O(1) extra memory, because the offsets arrive in order and the scan never needs to look back. The dense map allocated and zeroed EIGHT BYTES PER DOCUMENT BYTE on every keystroke of an incremental search; this allocates nothing.

Trait Implementations§

Source§

impl<'a> Clone for Ruler<'a>

Source§

fn clone(&self) -> Ruler<'a>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Copy for Ruler<'a>

Source§

impl<'a> Debug for Ruler<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Ruler<'a>

§

impl<'a> RefUnwindSafe for Ruler<'a>

§

impl<'a> Send for Ruler<'a>

§

impl<'a> Sync for Ruler<'a>

§

impl<'a> Unpin for Ruler<'a>

§

impl<'a> UnsafeUnpin for Ruler<'a>

§

impl<'a> UnwindSafe for Ruler<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.