stash
This commit is contained in:
parent
3299c97392
commit
de7d9426be
10 changed files with 259 additions and 99 deletions
|
|
@ -8,31 +8,37 @@ const SCHEMAS = {
|
|||
fields: ['owner_identity_id', 'item_local_id'],
|
||||
interpret: ([owner_identity_id, item_local_id]) => ({kind: 'item', owner_identity_id, item_local_id})
|
||||
},
|
||||
//0-1 left free for later use
|
||||
'1-2': {
|
||||
name: 'group_item',
|
||||
fields: ['owner_group_id', 'item_local_id'],
|
||||
interpret: ([owner_group_id, item_local_id]) => ({kind: 'group_item', owner_group_id, item_local_id})
|
||||
},
|
||||
'1-1': {
|
||||
name: 'group',
|
||||
fields: ['group_id'],
|
||||
interpret: ([group_id]) => ({kind: 'group', group_id})
|
||||
},
|
||||
'2-2': {
|
||||
name: 'storage_location',
|
||||
fields: ['owner_identity_id', 'storage_location_id'],
|
||||
interpret: ([owner_identity_id, storage_location_id]) =>
|
||||
({kind: 'storage_location', owner_identity_id, storage_location_id})
|
||||
},
|
||||
'2-1': {
|
||||
name: 'category',
|
||||
fields: ['category_id'],
|
||||
interpret: ([category_id]) => ({kind: 'category', category_id})
|
||||
name: 'file',
|
||||
fields: ['file_id'],
|
||||
interpret: ([file_id]) => ({kind: 'file', file_id})
|
||||
},
|
||||
'3-2': {
|
||||
name: 'workflow',
|
||||
fields: ['owner_identity_id', 'workflow_id'],
|
||||
interpret: ([owner_identity_id, workflow_id]) => ({kind: 'workflow', owner_identity_id, workflow_id})
|
||||
},
|
||||
'4-1': {
|
||||
name: 'group',
|
||||
fields: ['group_id'],
|
||||
interpret: ([group_id]) => ({kind: 'group', group_id})
|
||||
},
|
||||
'5-1': {
|
||||
name: 'file',
|
||||
fields: ['file_id'],
|
||||
interpret: ([file_id]) => ({kind: 'file', file_id})
|
||||
'3-1': {
|
||||
name: 'category',
|
||||
fields: ['category_id'],
|
||||
interpret: ([category_id]) => ({kind: 'category', category_id})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -82,6 +88,10 @@ class BitReader {
|
|||
}
|
||||
return value
|
||||
}
|
||||
|
||||
bitsLeft() {
|
||||
return this.bits.length - this.pos
|
||||
}
|
||||
}
|
||||
|
||||
function base64UrlToBits(text) {
|
||||
|
|
@ -128,25 +138,6 @@ function readChunkedInt(reader, chunkBits) {
|
|||
}
|
||||
}
|
||||
|
||||
function entriesForKindIndex(kindIndex) {
|
||||
return Object.entries(SCHEMAS).filter(([key]) => key.startsWith(`${kindIndex}-`))
|
||||
}
|
||||
|
||||
function schemaForKindIndex(kindIndex) {
|
||||
const matches = entriesForKindIndex(kindIndex)
|
||||
if (matches.length === 0) {
|
||||
throw new Error(`unknown short id kind index: ${kindIndex}`)
|
||||
}
|
||||
if (matches.length > 1) {
|
||||
throw new Error(
|
||||
`ambiguous short id kind index ${kindIndex}: base-level decoding needs exactly one `
|
||||
+ `field count per kind, found arities ${matches.map(([, s]) => s.fields.length).join(', ')} `
|
||||
+ `- only deserializeShortId's (kind, fields.length) lookup can tell those apart`
|
||||
)
|
||||
}
|
||||
return matches[0][1]
|
||||
}
|
||||
|
||||
function schemaForKindAndArity(kindIndex, arity) {
|
||||
const schema = SCHEMAS[`${kindIndex}-${arity}`]
|
||||
if (!schema) {
|
||||
|
|
@ -160,10 +151,12 @@ export function encodeShortId(ints) {
|
|||
throw new Error('short id must be a non-empty list of [kindIndex, ...fieldValues]')
|
||||
}
|
||||
const [kindIndex, ...fieldValues] = ints
|
||||
const schema = schemaForKindIndex(kindIndex)
|
||||
if (fieldValues.length !== schema.fields.length) {
|
||||
const schema = schemaForKindAndArity(kindIndex, fieldValues.length)
|
||||
if (fieldValues[fieldValues.length - 1] === 0) {
|
||||
throw new Error(
|
||||
`short id kind index ${kindIndex} ('${schema.name}') needs ${schema.fields.length} field value(s), got ${fieldValues.length}`
|
||||
`short id kind index ${kindIndex} ('${schema.name}'): the last field's value must not be 0 - `
|
||||
+ `reserved so decodeShortId can tell a real trailing field apart from zero-padding without `
|
||||
+ `knowing the kind's arity up front (see docs/handles-and-shortids.md)`
|
||||
)
|
||||
}
|
||||
const writer = new BitWriter()
|
||||
|
|
@ -188,8 +181,14 @@ export function decodeShortId(token) {
|
|||
if (kindIndex === DIRECT_KIND_COUNT) {
|
||||
kindIndex = DIRECT_KIND_COUNT + Number(readChunkedInt(reader, CHUNK_BITS))
|
||||
}
|
||||
const schema = schemaForKindIndex(kindIndex)
|
||||
const fieldValues = schema.fields.map(() => Number(readChunkedInt(reader, CHUNK_BITS)))
|
||||
const fieldValues = []
|
||||
while (reader.bitsLeft() >= CHUNK_BITS + 1) {
|
||||
const value = readChunkedInt(reader, CHUNK_BITS)
|
||||
if (value === 0n && reader.bitsLeft() === 0) {
|
||||
break // a trailing all-zero chunk with nothing after it is padding, not a real field
|
||||
}
|
||||
fieldValues.push(Number(value))
|
||||
}
|
||||
return [kindIndex, ...fieldValues]
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue