///|
/// User-facing text offsets. CRDT item clocks always count UTF-16 code units.
pub(all) enum OffsetKind {
Utf16
Bytes
} derive(Eq, Debug)
///|
pub extend OffsetKind with Eq::{equal, not_equal}
///|
pub extend OffsetKind with Debug::{to_repr}
///|
pub fn Doc::offset_kind(self : Doc) -> OffsetKind {
if self.wire_encoding == 1 {
Bytes
} else {
Utf16
}
}
///|
fn utf8_width(c : Char) -> Int32 {
let n = c.to_int()
if n < 0x80 {
1
} else if n < 0x800 {
2
} else if n < 0x10000 {
3
} else {
4
}
}
///|
fn Content::offset_length(self : Content, doc : Doc) -> Int32 {
if doc.wire_encoding == 1 && self is Characters(text) {
let mut length = 0
for c in text {
length += utf8_width(c)
}
length
} else {
self.visible_length()
}
}
///|
fn Content::block_offset(self : Content, offset : Int32, doc : Doc) -> Int32 {
if doc.wire_encoding == 1 && self is Characters(text) {
let mut remaining = offset
let mut clock = 0
for c in text {
if remaining == 0 {
break
}
remaining -= utf8_width(c)
guard remaining >= 0 else {
abort("text offset is not a UTF-8 character boundary")
}
clock += if c.to_int() > 0xffff { 2 } else { 1 }
}
guard remaining == 0 else { abort("text offset out of bounds") }
clock
} else {
offset
}
}