///|
pub(all) struct Point {
row : UInt32
column : UInt32
} derive(Eq, Debug)
///|
pub fn uint32_max() -> UInt32 {
4294967295U
}
///|
pub fn Point::new(row~ : UInt32, column~ : UInt32) -> Point {
{ row, column, }
}
///|
pub fn Point::zero() -> Point {
{ row: 0, column: 0, }
}
///|
pub fn Point::max() -> Point {
{ row: uint32_max(), column: uint32_max(), }
}
///|
pub fn Point::lt(self : Point, other : Point) -> Bool {
self.row < other.row || (self.row == other.row && self.column < other.column)
}
///|
pub fn Point::lte(self : Point, other : Point) -> Bool {
self.row < other.row || (self.row == other.row && self.column <= other.column)
}
///|
pub fn Point::gt(self : Point, other : Point) -> Bool {
self.row > other.row || (self.row == other.row && self.column > other.column)
}
///|
pub fn Point::gte(self : Point, other : Point) -> Bool {
self.row > other.row || (self.row == other.row && self.column >= other.column)
}
///|
pub fn Point::add(self : Point, other : Point) -> Point {
if other.row > 0 {
{ row: add_u32_saturating(self.row, other.row), column: other.column, }
} else {
{ row: self.row, column: add_u32_saturating(self.column, other.column), }
}
}
///|
pub fn Point::sub(self : Point, other : Point) -> Point {
if self.row > other.row {
{ row: self.row - other.row, column: self.column, }
} else {
{ row: 0, column: sub_u32_saturating(self.column, other.column), }
}
}
///|
pub fn Point::edit(
self : Point,
byte~ : UInt32,
edit~ : InputEdit,
) -> (UInt32, Point) {
edit.edit_position(byte~, point=self)
}
///|
pub(all) struct Range {
start_byte : UInt32
end_byte : UInt32
start_point : Point
end_point : Point
} derive(Eq, Debug)
///|
pub fn Range::new(
start_byte~ : UInt32,
end_byte~ : UInt32,
start_point~ : Point,
end_point~ : Point,
) -> Range {
{ start_byte, end_byte, start_point, end_point, }
}
///|
pub fn Range::unbounded(start_byte~ : UInt32, start_point~ : Point) -> Range {
{ start_byte, end_byte: uint32_max(), start_point, end_point: Point::max(), }
}
///|
pub fn Range::is_empty(self : Range) -> Bool {
self.start_byte == self.end_byte && self.start_point == self.end_point
}
///|
pub fn Range::contains_byte(self : Range, byte : UInt32) -> Bool {
self.start_byte <= byte && byte < self.end_byte
}
///|
pub fn Range::contains_point(self : Range, point : Point) -> Bool {
self.start_point.lte(point) && point.lt(self.end_point)
}
///|
pub fn Range::byte_length(self : Range) -> UInt32 {
sub_u32_saturating(self.end_byte, self.start_byte)
}
///|
pub fn Range::edit(self : Range, edit : InputEdit) -> Range {
let (end_byte, end_point) = edit_range_end(
byte=self.end_byte,
point=self.end_point,
edit~,
)
let (start_byte, start_point) = edit_range_start(
byte=self.start_byte,
point=self.start_point,
edit~,
)
{ start_byte, end_byte, start_point, end_point, }
}
///|
pub(all) struct InputEdit {
start_byte : UInt32
old_end_byte : UInt32
new_end_byte : UInt32
start_point : Point
old_end_point : Point
new_end_point : Point
} derive(Eq, Debug)
///|
pub fn InputEdit::new(
start_byte~ : UInt32,
old_end_byte~ : UInt32,
new_end_byte~ : UInt32,
start_point~ : Point,
old_end_point~ : Point,
new_end_point~ : Point,
) -> InputEdit {
{
start_byte,
old_end_byte,
new_end_byte,
start_point,
old_end_point,
new_end_point,
}
}
///|
pub fn InputEdit::edit_position(
self : InputEdit,
byte~ : UInt32,
point~ : Point,
) -> (UInt32, Point) {
if byte >= self.old_end_byte {
let delta = byte - self.old_end_byte
let (new_byte, overflowed) = add_u32_checked(self.new_end_byte, delta)
if overflowed {
(uint32_max(), Point::max())
} else {
let new_point = self.new_end_point.add(point.sub(self.old_end_point))
(new_byte, new_point)
}
} else if byte > self.start_byte {
(self.new_end_byte, self.new_end_point)
} else {
(byte, point)
}
}
///|
pub(all) enum InputEncoding {
Utf8
Utf16LE
Utf16BE
Custom
} derive(Eq, Debug)
///|
fn edit_range_end(
byte~ : UInt32,
point~ : Point,
edit~ : InputEdit,
) -> (UInt32, Point) {
if byte >= edit.old_end_byte {
if byte != uint32_max() {
let delta = byte - edit.old_end_byte
let (new_byte, overflowed) = add_u32_checked(edit.new_end_byte, delta)
if overflowed {
(uint32_max(), Point::max())
} else {
let new_point = edit.new_end_point.add(point.sub(edit.old_end_point))
(new_byte, new_point)
}
} else {
(byte, point)
}
} else if byte > edit.start_byte {
(edit.start_byte, edit.start_point)
} else {
(byte, point)
}
}
///|
fn edit_range_start(
byte~ : UInt32,
point~ : Point,
edit~ : InputEdit,
) -> (UInt32, Point) {
if byte >= edit.old_end_byte {
let delta = byte - edit.old_end_byte
let (new_byte, overflowed) = add_u32_checked(edit.new_end_byte, delta)
if overflowed {
(uint32_max(), Point::max())
} else {
let new_point = edit.new_end_point.add(point.sub(edit.old_end_point))
(new_byte, new_point)
}
} else if byte > edit.start_byte {
(edit.start_byte, edit.start_point)
} else {
(byte, point)
}
}
///|
fn add_u32_checked(left : UInt32, right : UInt32) -> (UInt32, Bool) {
if right > uint32_max() - left {
(uint32_max(), true)
} else {
(left + right, false)
}
}
///|
fn add_u32_saturating(left : UInt32, right : UInt32) -> UInt32 {
let (value, _) = add_u32_checked(left, right)
value
}
///|
fn sub_u32_saturating(left : UInt32, right : UInt32) -> UInt32 {
if left >= right {
left - right
} else {
0
}
}