_next_boundary

func _next_boundary(storage: ByteStorage, offset: Int, end: Int) -> Int

The byte offset just past the extended grapheme cluster starting at offset, which must itself be a cluster boundary. Because scans start at true boundaries, all UAX #29 rule state (GB11's emoji sequence, GB9c's conjunct chain, GB12/13's regional-indicator parity) is local to this one scan — the iterator carries none.

View Source
pub func _next_boundary(storage: ByteStorage, offset: Int, end: Int) -> Int {
	let head: Int = _utf8_decode(storage: storage, offset: offset, end: end)
	let head_cat: Int = _grapheme_category(scalar: _packed_scalar(packed: head))
	let pos: Int = offset + _packed_size(packed: head)
	// GB3/GB4: CR joins only a following LF; controls stand alone.
	if head_cat == _GC_CR {
		if pos < end {
			let after_cr: Int = _utf8_decode(storage: storage, offset: pos, end: end)
			if _packed_scalar(packed: after_cr) == 10 { return pos + _packed_size(
				packed: after_cr
			) }
		}
		return pos
	}
	if head_cat == _GC_CONTROL { return pos }
	if head_cat == _GC_LF { return pos }
	let prev: Int = head_cat
	// GB11 state: 0 none, 1 ExtPict (+ extends), 2 ExtPict + extends + ZWJ.
	let emoji: Int = 0
	if head_cat == _GC_EXT_PICT { emoji = 1 }
	// GB9c state: 0 none, 1 consonant (+ InCB extends), 2 consonant + linker.
	let incb: Int = 0
	if head_cat == _GC_INCB_CONSONANT { incb = 1 }
	// GB12/13 state: length of the trailing regional-indicator run.
	let ri_run: Int = 0
	if head_cat == _GC_REGIONAL_INDICATOR { ri_run = 1 }
	loop pos < end {
		let next_packed: Int = _utf8_decode(storage: storage, offset: pos, end: end)
		let cat: Int = _grapheme_category(scalar: _packed_scalar(packed: next_packed))
		if _joins(prev: prev, cat: cat, emoji: emoji, incb: incb, ri_run: ri_run) == false { return pos }
		if cat == _GC_EXT_PICT {
			emoji = 1
		} else {
			let emoji_extends: Bool = emoji == 1 && _extends_cluster(cat: cat)
			if emoji_extends {
				if cat == _GC_ZWJ { emoji = 2 }
			} else {
				emoji = 0
			}
		}
		if cat == _GC_INCB_CONSONANT {
			incb = 1
		} else {
			let links: Bool = incb >= 1 && cat == _GC_EXTEND_INCB_LINKER
			let carries: Bool = incb >= 1 && (cat == _GC_EXTEND_INCB_EXTEND || cat == _GC_ZWJ)
			if links {
				incb = 2
			} else {
				if carries == false { incb = 0 }
			}
		}
		if cat == _GC_REGIONAL_INDICATOR {
			if prev == _GC_REGIONAL_INDICATOR {
				ri_run = ri_run + 1
			} else {
				ri_run = 1
			}
		} else {
			ri_run = 0
		}
		prev = cat
		pos = pos + _packed_size(packed: next_packed)
	}
	pos
}