| 243 | * @returns {string} the checked Changeset |
| 244 | */ |
| 245 | export const checkRep = (cs: string) => { |
| 246 | const unpacked = unpack(cs); |
| 247 | const oldLen = unpacked.oldLen; |
| 248 | const newLen = unpacked.newLen; |
| 249 | const ops = unpacked.ops; |
| 250 | let charBank = unpacked.charBank; |
| 251 | |
| 252 | const assem = new SmartOpAssembler(); |
| 253 | let oldPos = 0; |
| 254 | let calcNewLen = 0; |
| 255 | for (const o of deserializeOps(ops)) { |
| 256 | switch (o.opcode) { |
| 257 | case '=': |
| 258 | oldPos += o.chars; |
| 259 | calcNewLen += o.chars; |
| 260 | break; |
| 261 | case '-': |
| 262 | oldPos += o.chars; |
| 263 | assert(oldPos <= oldLen, `${oldPos} > ${oldLen} in ${cs}`); |
| 264 | break; |
| 265 | case '+': |
| 266 | { |
| 267 | assert(charBank.length >= o.chars, 'Invalid changeset: not enough chars in charBank'); |
| 268 | const chars = charBank.slice(0, o.chars); |
| 269 | const nlines = (chars.match(/\n/g) || []).length; |
| 270 | assert(nlines === o.lines, |
| 271 | 'Invalid changeset: number of newlines in insert op does not match the charBank'); |
| 272 | assert(o.lines === 0 || chars.endsWith('\n'), |
| 273 | 'Invalid changeset: multiline insert op does not end with a newline'); |
| 274 | charBank = charBank.slice(o.chars); |
| 275 | calcNewLen += o.chars; |
| 276 | assert(calcNewLen <= newLen, `${calcNewLen} > ${newLen} in ${cs}`); |
| 277 | break; |
| 278 | } |
| 279 | default: |
| 280 | assert(false, `Invalid changeset: Unknown opcode: ${JSON.stringify(o.opcode)}`); |
| 281 | } |
| 282 | assem.append(o); |
| 283 | } |
| 284 | calcNewLen += oldLen - oldPos; |
| 285 | assert(calcNewLen === newLen, 'Invalid changeset: claimed length does not match actual length'); |
| 286 | assert(charBank === '', 'Invalid changeset: excess characters in the charBank'); |
| 287 | assem.endDocument(); |
| 288 | const normalized = pack(oldLen, calcNewLen, assem.toString(), unpacked.charBank); |
| 289 | assert(normalized === cs, 'Invalid changeset: not in canonical form'); |
| 290 | return cs; |
| 291 | }; |
| 292 | |
| 293 | /** |
| 294 | * A custom made StringBuffer |