# std/strpred

The string predicates and `slice`, written on the byte view (`bytes`, `s[i]`, `stringFromBytes`).

Offsets and lengths are bytes. A byte-wise scan is safe on UTF-8: a valid needle starts with an ASCII or a lead byte, so it cannot match at a continuation byte. The functions read the `byteLength` field, never `byteLengthV`: the field is O(1) and folds at compile time, while `byteLengthV` copies the string (4.5 ns against 72.5 ns on 47 bytes). The `s.byteLength` field as a function.

## byteLengthV

`fn`, at line 11.

```vyrn
fn byteLengthV(s: String) -> Int64
```

The `s.byteLength` field as a function.

## startsWith

`fn`, at line 19.

```vyrn
fn startsWith(s: String, needle: String) -> Bool
```

Does `s` begin with `needle`? An empty needle is a prefix of everything.

## endsWith

`fn`, at line 35.

```vyrn
fn endsWith(s: String, needle: String) -> Bool
```

Does `s` end with `needle`? An empty needle is a suffix of everything.

## skipTable

`fn`, at line 55.

```vyrn
fn skipTable(needle: String, haystackBytes: Int64) -> Array<UInt32>
```

Boyer-Moore-Horspool's bad-character table for `needle`: for each byte, how far a window may jump when it ends on that byte. A plain `Array`, not a record: a field read per byte costs the interpreter measurably, and an array argument is shared copy-on-write.

## findPlain

`fn`, at line 78.

```vyrn
fn findPlain(s: String, needle: String, from: Int64 where value >= 0) -> Option<Int64>
```

The first occurrence of `needle` at or after `from`, or `None`. A found offset is at most `s.byteLength - needle.byteLength`, so an empty needle occurs at `from` only when `from <= s.byteLength`. O(n*m).

## worthPreparing

`fn`, at line 98.

```vyrn
fn worthPreparing(needle: String, haystackBytes: Int64) -> Bool
```

Whether a table for `needle` pays over a haystack of that size. Callers ask before building the table: `std/vyx` calls `contains` on short strings millions of times, and an allocation per call cost it about 10%.

## findSkipping

`fn`, at line 105.

```vyrn
fn findSkipping(s: String, needle: String, from: Int64 where value >= 0, skip: Array<UInt32> where value.length >= 256) -> Option<Int64>
```

[`findPlain`](#e-findPlain) with a table from [`skipTable`](#e-skipTable): it compares from the end of the window and, on a mismatch, skips by the table entry for the window's last byte, so it visits about `n / m` positions.

## contains

`fn`, at line 127.

```vyrn
fn contains(s: String, needle: String) -> Bool
```

Whether `needle` occurs in `s`; an empty needle occurs everywhere.

## SliceError

`type`, at line 157.

```vyrn
type SliceError = enum { OutOfRange(Int64), SplitsCharacter(Int64) }
```

The two ways a byte range fails to name a substring, each carrying the offset that failed.

## slice

`fn`, at line 170.

```vyrn
fn slice(s: String, start: Int64, end: Int64) -> Result<String, SliceError>
```

The bytes of `s` from `start` up to `end`, both byte offsets on UTF-8 character boundaries.

`OutOfRange(start)` when `start < 0`; `OutOfRange(end)` when `end > s.byteLength` or `start > end`. `SplitsCharacter(i)` when cut point `i` lands on a continuation byte. The range is checked before the boundary, as `examples/strpredbytes.vyrn` pins. A string that holds NUL, which no program can construct, returns `SplitsCharacter(start)`.

It reads `s[i]` and `s.byteLength`, never `bytes(s)`: `std/scan` slices once per token, so a whole-string copy per call would be quadratic.

---

From https://vyrn-lang.github.io/docs/std/strpred.html — generated by `site/export.vyrn` from the Vyrn repository.
