Skip to main content

FoldedText

Struct FoldedText 

Source
pub struct FoldedText { /* private fields */ }
Expand description

A haystack folded once, ready to be searched many times.

§Why this exists

A project-wide search box re-searches the same prose on every keystroke, and folding it is not free. Measured over a 300k-word manuscript: the fold costs about the same as parsing the prose in the first place, and roughly twice what scanning it does — and it was being rebuilt from scratch for every character the writer typed. A host app holds one of these per scene and pays that cost once.

§What it is keyed by, and what it is not

It is built from a FoldSpec — case, diacritics, language — because those are what decide how a character folds. whole_word is not one of them: it decides which matches survive, not how the text folds. So it is a parameter of find_all, not of the fold, and one FoldedText answers both kinds of query. That is not a nicety: it means ticking “whole word” does not throw away a manuscript’s worth of folding.

The word-boundary table is built lazily, on the first whole-word query, because it is a second full pass over the text and most searches never ask for it.

Implementations§

Source§

impl FoldedText

Source

pub fn new(haystack: &str, spec: &FoldSpec) -> FoldedText

Fold haystack under spec. (MatchOptions::fold_spec gets you one.)

Source

pub fn source(&self) -> &str

The original text — what the offsets below address, and what a snippet is cut from.

Source

pub fn find_all(&self, needle: &str, whole_word: bool) -> Vec<Match>

Every occurrence of needle, in original char offsets.

whole_word is decided here rather than at fold time; see the type’s docs.

Source

pub fn prepare_word_boundaries(&self)

Build the word-boundary table now, rather than on the first whole-word query.

A caller that caches a FoldedText should call this, and the reason is heap_size, not speed. The table is lazy so that the throwaway path — fold, search once, drop — does not pay a UAX#29 pass it never uses. But a cached instance is measured once, when it is stored, and then grows silently the first time someone ticks “whole word”: its recorded size is stale from that moment on, and a cache bounded by the sum of those sizes holds materially more than it believes.

Forcing it here makes the size final, so what the cache measures is what it has.

Source

pub fn heap_size(&self) -> usize

Roughly how many bytes of heap this holds.

A host app caching one per scene has to bound the total, and the honest number is not obvious: the index maps are four bytes per folded char, so together they outweigh the text itself several times over.

Not stable until prepare_word_boundaries has been called — the boundary table is built lazily, so before then this under-reports by whatever that table will come to weigh.

Auto Trait Implementations§

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> 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> Same for T

Source§

type Output = T

Should always be Self
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.