Skip to content

Commit

Permalink
[mendoza] Smarter rebasing of strings
Browse files Browse the repository at this point in the history
  • Loading branch information
judofyr authored and rexxars committed Oct 6, 2020
1 parent d42fe24 commit c28cb6b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 3 deletions.
32 changes: 29 additions & 3 deletions packages/mendoza/src/incremental-patcher.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable max-statements */
/* eslint-disable yoda */
/* eslint-disable default-case */
/* eslint-disable class-methods-use-this */
/* eslint-disable no-else-return */
Expand All @@ -6,7 +8,7 @@
import {ObjectModel} from './object-model'
import {RawPatch} from './patch'
import {Patcher} from './internal-patcher'
import {utf8charSize, utf8stringSize} from './utf8'
import {utf8charSize, utf8stringSize, commonPrefix, commonSuffix} from './utf8'

// The incremental patcher allows you to apply multiple patches and tracks the history of every element.
// It also allows you to extract a simple diff between the documents.
Expand Down Expand Up @@ -410,11 +412,35 @@ export function rebaseValue<T>(left: Value<T>, right: Value<T>): Value<T> {
}
case 'null':
case 'boolean':
case 'number':
case 'string': {
case 'number': {
if (unwrap(left) === unwrap(right)) return left
break
}
case 'string': {
let leftRaw = unwrap(left) as string
let rightRaw = unwrap(right) as string
if (leftRaw === rightRaw) return left

let result = rightModel.copyString(null)
let prefix = commonPrefix(leftRaw, rightRaw)
let suffix = commonSuffix(leftRaw, rightRaw)

let rightLen = utf8stringSize(rightRaw)
let leftLen = utf8stringSize(leftRaw)

if (0 < prefix) {
rightModel.stringAppendSlice(result, left, 0, prefix)
}
if (prefix < rightLen - suffix) {
rightModel.stringAppendSlice(result, right, prefix, rightLen - suffix)
}
if (leftLen - suffix < leftLen) {
rightModel.stringAppendSlice(result, left, leftLen - suffix, leftLen)
}
let value = rightModel.finalize(result)
if (unwrap(value) !== rightRaw) throw new Error('incorrect string rebase')
return value
}
}

return right
Expand Down
28 changes: 28 additions & 0 deletions packages/mendoza/src/utf8.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,31 @@ export function utf8resolveIndex(str: string, idx: number, start = 0) {

return ucsIdx
}

export function commonPrefix(str: string, str2: string) {
let len = Math.min(str.length, str2.length)
let b = 0
for (let i = 0; i < len; ) {
let aPoint = str.codePointAt(i)!
let bPoint = str2.codePointAt(i)!
if (aPoint !== bPoint) return b
let size = utf8charSize(aPoint)
b += size
i += size === 4 ? 2 : 1
}
return b
}

export function commonSuffix(str: string, str2: string) {
let len = Math.min(str.length, str2.length)
let b = 0
for (let i = 0; i < len; ) {
let aPoint = str.codePointAt(str.length - 1 - i)!
let bPoint = str2.codePointAt(str2.length - 1 - i)!
if (aPoint !== bPoint) return b
let size = utf8charSize(aPoint)
b += size
i += size === 4 ? 2 : 1
}
return b
}

0 comments on commit c28cb6b

Please sign in to comment.