enso/app/gui2/ydoc-server/serialization.ts
Kaz Wesley 19d0707334
Preparing for AST-based synchronization (#8625)
Further AST integration and API refinement before introducing the new synchronization mechanism.

closes #8609

# Important Notes
API changes:
- Renamed `Ast.parseExpression` / `Ast.parse` to better reflect their usage:
- `Ast.parse` returns a block or a single expression, depending on its input; this is convenient for expressions expected to be single-line.
- `Ast.parseBlock` always treats its input as a block; this is suitable for parsing a file.
- `astExtended` is no longer needed to access span information. `Ast.span` provides access to the value when appropriate (the project's committed modules have spans; uncommitted changes or other parsed expressions don't).
- `SourceRange` is now used everywhere in place of `ContentRange`--the two types had the same definition.

Features:
- Fix CodeEditor viewing.

Implementation improvements:
- Updated widget update handlers (#8545) implementation to Ast API.
- Integrated `imports` more thoroughly with new AST APIs.
- More tests.
2024-01-02 15:18:11 +00:00

50 lines
1.6 KiB
TypeScript

/** Translation of `yjsModel` types to and from the `fileFormat` representation. */
import * as json from 'lib0/json'
import { ExprId, IdMap } from '../shared/yjsModel'
import * as fileFormat from './fileFormat'
export function deserializeIdMap(idMapJson: string) {
const idMapMeta = fileFormat.tryParseIdMapOrFallback(idMapJson)
const idMap = new IdMap()
for (const [{ index, size }, id] of idMapMeta) {
const range = [index.value, index.value + size.value]
if (typeof range[0] !== 'number' || typeof range[1] !== 'number') {
console.error(`Invalid range for id ${id}:`, range)
continue
}
idMap.insertKnownId([index.value, index.value + size.value], id as ExprId)
}
return idMap
}
export function serializeIdMap(map: IdMap): string {
map.validate()
return json.stringify(idMapToArray(map))
}
function idMapToArray(map: IdMap): fileFormat.IdMapEntry[] {
const entries: fileFormat.IdMapEntry[] = []
map.entries().forEach(([rangeBuffer, id]) => {
const decoded = IdMap.rangeForKey(rangeBuffer)
const index = decoded[0]
const endIndex = decoded[1]
if (index == null || endIndex == null) return
const size = endIndex - index
entries.push([{ index: { value: index }, size: { value: size } }, id])
})
entries.sort(idMapCmp)
return entries
}
function idMapCmp(a: fileFormat.IdMapEntry, b: fileFormat.IdMapEntry) {
const val1 = a[0]?.index?.value ?? 0
const val2 = b[0]?.index?.value ?? 0
if (val1 === val2) {
const size1 = a[0]?.size.value ?? 0
const size2 = b[0]?.size.value ?? 0
return size1 - size2
}
return val1 - val2
}