Skip to content

Instantly share code, notes, and snippets.

@cyppan
Last active November 19, 2020 12:39
Show Gist options
  • Save cyppan/e4b3963c5642a0176a330ee640d379b7 to your computer and use it in GitHub Desktop.
Save cyppan/e4b3963c5642a0176a330ee640d379b7 to your computer and use it in GitHub Desktop.
Javascript (very incomplete) port of the "unserialize" PHP function
function unserialize(serialized) {
serialized = serialized.split("")
const res = []
const parseNumber = () => {
next = serialized.shift()
let digits = ""
while (!isNaN(parseInt(next))) {
digits += next
next = serialized.shift()
}
return { value: parseInt(digits), next }
}
const parseString = (len) => {
serialized.shift() // remove quote
const str = serialized.splice(0, len)
serialized.shift() // remove quote
return { value: str.join(""), next: serialized.shift() }
}
const parseBool = () => {
const value = serialized.shift()
const next = serialized.shift()
return { value, next }
}
const parse = (obj = [], parents = []) => {
if (serialized.length === 0) return obj
const type = serialized.shift()
let parsed = { value: null, next: null }
if (type === 'i') { // number (we only support ints)
serialized.shift()
parsed = parseNumber()
obj.push(parsed.value)
} else if (type === 's') { // string
serialized.shift()
const { value: len, next } = parseNumber()
parsed = parseString(len)
obj.push(parsed.value)
} else if (type === 'a') { // assocative array (map)
serialized.shift()
const { value: len, next } = parseNumber()
serialized.shift()
const childObj = []
obj.push(childObj)
parse(childObj, [...parents, obj])
} else if (type === '}') {
parse(parents[parents.length - 1], parents.slice(0, parents.length - 1))
} else if (type === 'b') { // boolean
serialized.shift()
parsed = parseBool()
} else if (type === 'N') { // null
parsed = { value: null, next: serialized.shift() }
} else {
console.error(obj)
throw new Error("unsupported serialized type " + type + obj.join(" "))
}
if (parsed.next === ';') {
parse(obj, parents)
}
return obj
}
const associativeArrayToMap = (arr) => {
const map = {}
const len = arr.length
for (let i = 0; i < len / 2; i++) {
let [key, val] = arr.splice(0, 2)
if (Array.isArray(val)) {
val = associativeArrayToMap(val)
}
map[key] = val
}
return map
}
return associativeArrayToMap(parse(res)[0])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment