Skip to content

Instantly share code, notes, and snippets.

@hackwaly
Created January 21, 2022 16:32
Show Gist options
  • Save hackwaly/033c295764153519fcf3fcf69830f1c9 to your computer and use it in GitHub Desktop.
Save hackwaly/033c295764153519fcf3fcf69830f1c9 to your computer and use it in GitHub Desktop.
// Generated by ReScript, PLEASE EDIT WITH CARE
import * as Caml_array from "rescript/lib/es6/caml_array.js";
function cons(_record, _map) {
while(true) {
var map = _map;
var record = _record;
if (!map) {
return {
hd: record,
tl: /* [] */0
};
}
var right = map.hd;
if (record.op !== right.op) {
return {
hd: record,
tl: map
};
}
_map = map.tl;
_record = {
op: record.op,
length: record.length + right.length | 0
};
continue ;
};
}
function fromArray(records) {
var _result = /* [] */0;
var _index = records.length - 1 | 0;
while(true) {
var index = _index;
var result = _result;
if (index === -1) {
return result;
}
_index = index - 1 | 0;
_result = cons(Caml_array.get(records, index), result);
continue ;
};
}
function compose(_left, _right) {
while(true) {
var right = _right;
var left = _left;
if (!right) {
return left;
}
if (!left) {
return right;
}
var record = right.hd;
if (record.op === "insert") {
return cons(record, compose(left, right.tl));
}
var record$1 = left.hd;
if (record$1.op === "delete") {
return cons(record$1, compose(left.tl, right));
}
var rightRecord = right.hd;
var left$1 = left.tl;
var left$2 = record$1.length > rightRecord.length ? cons({
op: record$1.op,
length: record$1.length - rightRecord.length | 0
}, left$1) : left$1;
var right$1 = rightRecord.length > record$1.length ? cons({
op: rightRecord.op,
length: rightRecord.length - record$1.length | 0
}, left$2) : right.tl;
if (rightRecord.op === "retain") {
return cons({
op: record$1.op,
length: record$1.length < rightRecord.length ? record$1.length : rightRecord.length
}, compose(left$2, right$1));
}
_right = right$1;
_left = left$2;
continue ;
};
}
function mapOffset(_map, _offset, preferRight) {
while(true) {
var offset = _offset;
var map = _map;
if (!map) {
return offset;
}
var match = map.hd;
var match$1 = match.op;
if (match$1 === "retain") {
var length = match.length;
if (offset < length) {
return offset;
} else {
return length + mapOffset(map.tl, offset - length | 0, preferRight) | 0;
}
}
if (match$1 === "insert") {
if (offset === 0 && !preferRight) {
return 0;
} else {
return match.length + mapOffset(map.tl, offset, preferRight) | 0;
}
}
var length$1 = match.length;
if (offset < length$1) {
return 0;
}
_offset = offset - length$1 | 0;
_map = map.tl;
continue ;
};
}
export {
fromArray ,
compose ,
mapOffset ,
}
/* No side effect */
type changeRecord = {
op: [#insert | #delete | #retain],
length: int,
}
type changeMap = list<changeRecord>
let rec cons = (. record, map) => {
switch (record, map) {
| (record, list{}) => list{record}
| (left, list{right, ...map}) if left.op == right.op =>
cons(. {...left, length: left.length + right.length}, map)
| _ => list{record, ...map}
}
}
let fromArray = (. records: array<changeRecord>): changeMap => {
let rec aux = (. result, records, index) => {
if index == -1 {
result
} else {
aux(. cons(. records[index], result), records, index - 1)
}
}
aux(. list{}, records, Array.length(records) - 1)
}
let rec compose = (. left: changeMap, right: changeMap): changeMap => {
switch (left, right) {
| (left, list{}) => left
| (list{}, right) => right
| (left, list{{op: #insert} as record, ...right}) => cons(. record, compose(. left, right))
| (list{{op: #delete} as record, ...left}, right) => cons(. record, compose(. left, right))
| (list{leftRecord, ...left}, list{rightRecord, ...right}) =>
let left = if leftRecord.length > rightRecord.length {
cons(. {...leftRecord, length: leftRecord.length - rightRecord.length}, left)
} else {
left
}
let right = if rightRecord.length > leftRecord.length {
cons(. {...rightRecord, length: rightRecord.length - leftRecord.length}, left)
} else {
right
}
if rightRecord.op == #retain {
cons(.
{...leftRecord, length: min(leftRecord.length, rightRecord.length)},
compose(. left, right),
)
} else {
compose(. left, right)
}
}
}
let rec mapOffset = (. map: changeMap, offset: int, preferRight: bool) => {
switch map {
| list{} => offset
| list{{op: #insert, length}, ...map} =>
if offset == 0 && !preferRight {
0
} else {
length + mapOffset(. map, offset, preferRight)
}
| list{{op: #delete, length}, ...map} =>
if offset < length {
0
} else {
mapOffset(. map, offset - length, preferRight)
}
| list{{op: #retain, length}, ...map} =>
if offset < length {
offset
} else {
length + mapOffset(. map, offset - length, preferRight)
}
}
}
type changeRecord = {
op: [#insert | #delete | #retain],
length: int,
}
type changeMap
let fromArray: (. array<changeRecord>) => changeMap
let compose: (. changeMap, changeMap) => changeMap
let mapOffset: (. changeMap, int, bool) => int
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment