// Am I happy with this? Not particulary. Vague challenge wanted// a binary tree serializer/deserializer, but did not give any// other details about if the nodes only would take scalar values// or complex objects.// So... general solution to encode/decode any object using a// simple type prefix notation. Could be packed more if I allowed// binary representation (create byte length variations for// types, replace number type with binary types).functionserialize(obj){if(obj===undefined)obj='u'elseif(obj===null)obj='U'elseif(typeofobj==='boolean')obj=`b${+!!obj}`elseif(typeofobj==='string')obj=`s${obj.length}:${obj}`elseif(objinstanceofArray)obj=`a${obj.length}${obj.map(i=>serialize(i)).join('')}`elseif(typeofobj==='number'){if(isNaN(obj))obj='N'elseif(obj===-Infinity)obj='i'elseif(obj===Infinity)obj='I'elseobj=`n${obj}`}elseif(typeofobj==='function'){try{// Throws on bound or native function, make undefined in that caseobj=obj.toString()Function(`(${obj})`)()obj=`f${obj.length}:${obj}`}catch(e){obj='u'}}elseif(typeofobj==='object'){letcollected=[undefined]letcount=0for(letkeyinobj){collected.push(`s${key.length}:${key}${serialize(obj[key])}`)++count}collected[0]=`o${count}`obj=collected.join('')}returnobj}functiondeserialize(str){letindex=0returnstr.length?next():undefinedfunctionexpect(char){if(str[index++]!==char)thrownewError(`Missing ${char} separator at ${index-1}`)}functionnext(){switch(str[index++]){case'a':returnnextArray()case'b':returnstr[index++]===1case'f':returnFunction(`return (${nextString()})`)()case'i':return-Infinitycase'I':returnInfinitycase'n':returnnextNumber()case'N':returnNaNcase'o':returnnextObject()case's':returnnextString()case'u':returnundefinedcase'U':returnnulldefault:thrownewError(`Bad token at ${index-1}: ${str[index-1]}`)}}functionnextArray(){letlen=nextNumber()|0,ret=[]if(len<0)thrownewError(`Bad array length at ${index-1}: ${len}`)while(len--)ret.push(next())returnret}functionnextNumber(){letnum=str.slice(index).match(/-?(\d+(\.\d*)?|\.\d+)/)if(!num)thrownewError(`Number expected at ${index-1}`)index+=num[0].lengthreturn+num[0]}functionnextObject(){letlen=nextNumber()|0,ret={}if(len<0)thrownewError(`Bad object at ${index-1}: ${len}`)while(len--){expect('s')ret[nextString()]=next()}returnret}functionnextString(){letlen=nextNumber()expect(':')index+=lenreturnstr.substr(index-len,len)}}
Comments (0)
HTTPSSSH
You can clone a snippet to your computer for local editing.
Learn more.