zip 32 64 encoder logic
encoder[2.0, 4.5] available via webkitRelativePath.encoder
01. declare b, offset, sizelet b,offset=0n,size=0n02. declare length, values
const length=BigInt(fs.length),vs=Array(length<<1n)03. declare versionMadeBy, versionNeededToExtract
,versionMadeBy=new Uint8Array(2),versionNeededToExtract=new Uint8Array(2),d=(v=>v?v[0]:``)(fs[0].webkitRelativePath.match(/[^/]+\//))04. declare setVersion
,setVersion=v=>{
versionMadeBy.set(new Uint8Array([v]))
versionNeededToExtract.set(v.to2Array())
}05. set datetime
if(datetime)datetime=datetime.to4Array()06. start loop
for(let i0=0,i1=length;i0<fs.length;i0++,i1++){07. declare file, name
const f=fs[i0],name=encoder.encode(f.webkitRelativePath.replace(d,``))08. declare fileHeader, centralFileHeader, localFileHeader
,fileHeader=new Uint8Array(22),centralFileHeader=new Uint8Array(38+name.length),localFileHeader=new Uint8Array(24+name.length)09. declare data
,data=(v=>{
fileHeader.set(v[1].to4Array(),8)
if(f.size>v[0].size){
fileHeader.set((8).to2Array(),2)
return v[0]
}
return f
})(await c(type,blockSize,dictionarySize,searchSize,f,i0,message))10. set values
vs[i0]=[signatures[1],versionNeededToExtract,localFileHeader]
vs[i1]=[signatures[0],versionMadeBy,versionNeededToExtract,centralFileHeader]11. set fileHeader
fileHeader.set(generalPurposeBitFlag)
fileHeader.set(datetime?datetime:new Date(f.lastModified).toDateTime32().to4Array(),4)
fileHeader.set(data.size.to4Array(),12)
fileHeader.set(f.size.to4Array(),16)
fileHeader.set(name.length.to2Array(),20)12. set local_file_header
localFileHeader.set(fileHeader)
localFileHeader.set(name,24)13. set central_file_header
centralFileHeader.set(fileHeader)
centralFileHeader.set(Number(offset).to4Array(),34)
centralFileHeader.set(name,38)14. set central_file_header_extra, local_file_header_extra
if(0xffffffff<data.size||0xffffffff<f.size||0xffffffff<offset)(c=>{
const centralFileHeaderExtra=[],localFileHeaderExtra=[]
b|=1
if(0xffffffff<offset)centralFileHeaderExtra.push(offset.to8Array())
if(0xffffffff<f.size)localFileHeaderExtra.push(BigInt(f.size).to8Array())
if(0xffffffff<data.size)localFileHeaderExtra.push(BigInt(data.size).to8Array())
if(localFileHeaderExtra.length){
centralFileHeaderExtra.push(...localFileHeaderExtra)
c(vs[i0],localFileHeader,localFileHeaderExtra)
}
if(centralFileHeaderExtra.length)c(vs[i1],centralFileHeader,centralFileHeaderExtra)
})((vs,fileHeader,fileHeaderExtra)=>{
const size=fileHeaderExtra.length<<3,length=4+size
fileHeader.set(length.to2Array(),22)
vs.push((vs=>{
vs.set(signatures[2])
vs.set(size.to2Array(),2)
forEach(false,fileHeaderExtra,(v,i)=>vs.set(v,length-(1+i<<3)))
return vs
})(new Uint8Array(length)))
})15. add offset
offset+=BigInt(reduce(false,vs[i0],(a,v)=>a+v.length,0))
vs[i0].push(data)
offset+=BigInt(data.size)16. add size
size+=BigInt(reduce(false,vs[i1],(a,v)=>a+v.length,0))17. end loop
}18. start if
if(b||0xffff<fs.length||0xffffffff<size||0xffffffff<offset){19. set version
setVersion(45)20. set zip64_end_of_central_directory_record
vs.push(signatures[3],(vs=>{
vs.set(BigInt(44).to8Array())
vs.set(versionMadeBy,8)
vs.set(versionNeededToExtract,10)
vs.set(length.to8Array(),20)
vs.set(vs.subarray(20,28),28)
vs.set(size.to8Array(),36)
vs.set(offset.to8Array(),44)
return vs
})(new Uint8Array(52)))21. set zip64_end_of_central_directory_locator
vs.push(signatures[4],(vs=>{
vs.set((size+offset).to8Array(),4)
return vs
})(new Uint8Array(16)))22. end if, else set version
}else setVersion(20)23. set end_of_central_directory_record
vs.push(signatures[5],(vs=>{
vs.set(fs.length.to2Array(),4)
vs.set(vs.subarray(4,6),6)
vs.set(Number(size).to4Array(),8)
vs.set(Number(offset).to4Array(),12)
return vs
})(new Uint8Array(18)))24. return
return new File(vs.toValues(),d.slice(0,-1),{type:`application/zip`})