# Unicode Segmentation

> StringZilla for C#

The segmentation primitive is allocation-free: it fills the caller's span with segment lengths and returns the count.
Segments tile the text, so each starts where the previous one ended.

```csharp
long runeCount = Sz.CountRunes(text);    // cf. counting System.Text.Rune
int decoded = Sz.Decode(text, codepoints); // fill a Span<int>; ill-formed or truncated -> U+FFFD

Span<long> lengths = stackalloc long[64];
int count = Sz.Segment(text, Sz.SegmentKind.Words, lengths); // UAX-29
ReadOnlySpan<byte> rest = text;
foreach (long length in lengths[..count]) {
    Use(rest[..(int)length]);
    rest = rest[(int)length..];
}
// Kinds: Graphemes (cf. StringInfo), Words, Sentences, LineBreaks (UAX-14)
```

Codepoints count scalar values, not bytes or UTF-16 chars.
Segmentation _tiles_ the text — every byte belongs to exactly one segment — and a grapheme cluster can span several codepoints.

```csharp
Sz.CountRunes("你好世界"u8);                     // 4 codepoints
Sz.CountRunes("Hello🌍"u8);                      // 6 — the astral emoji is one scalar

foreach (var cluster in Sz.EnumerateGraphemes("👍🏽🇺🇸"u8)) Use(cluster); // 2 clusters: 👍🏽 (emoji + skin tone), 🇺🇸 (flag)
foreach (var word in Sz.EnumerateWords("Hello, 世界"u8)) Use(word);      // Latin run, then CJK run
```

