forked from sheetjs/sheetjs
		
	
		
			
	
	
		
			119 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			119 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | /*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */ | ||
|  | import { u8concat } from "./util"; | ||
|  | 
 | ||
|  | type Ptr = [number]; | ||
|  | export { Ptr }; | ||
|  | 
 | ||
|  | /** Parse an integer from the varint that can be exactly stored in a double */ | ||
|  | function parse_varint49(buf: Uint8Array, ptr?: Ptr): number { | ||
|  | 	var l = ptr ? ptr[0] : 0; | ||
|  | 	var usz = buf[l] & 0x7F; | ||
|  | 	varint: if(buf[l++] >= 0x80) { | ||
|  | 		usz |= (buf[l] & 0x7F) <<  7; if(buf[l++] < 0x80) break varint; | ||
|  | 		usz |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) break varint; | ||
|  | 		usz |= (buf[l] & 0x7F) << 21; if(buf[l++] < 0x80) break varint; | ||
|  | 		usz += (buf[l] & 0x7F) * Math.pow(2, 28); ++l; if(buf[l++] < 0x80) break varint; | ||
|  | 		usz += (buf[l] & 0x7F) * Math.pow(2, 35); ++l; if(buf[l++] < 0x80) break varint; | ||
|  | 		usz += (buf[l] & 0x7F) * Math.pow(2, 42); ++l; if(buf[l++] < 0x80) break varint; | ||
|  | 	} | ||
|  | 	if(ptr) ptr[0] = l; | ||
|  | 	return usz; | ||
|  | } | ||
|  | export { parse_varint49 }; | ||
|  | function write_varint49(v: number): Uint8Array { | ||
|  | 	var usz = new Uint8Array(7); | ||
|  | 	usz[0] = (v & 0x7F); | ||
|  | 	var L = 1; | ||
|  | 	sz: if(v > 0x7F) { | ||
|  | 		usz[L-1] |= 0x80; usz[L] = (v >> 7) & 0x7F; ++L; | ||
|  | 		if(v <= 0x3FFF) break sz; | ||
|  | 		usz[L-1] |= 0x80; usz[L] = (v >> 14) & 0x7F; ++L; | ||
|  | 		if(v <= 0x1FFFFF) break sz; | ||
|  | 		usz[L-1] |= 0x80; usz[L] = (v >> 21) & 0x7F; ++L; | ||
|  | 		if(v <= 0xFFFFFFF) break sz; | ||
|  | 		usz[L-1] |= 0x80; usz[L] = ((v/0x100) >>> 21) & 0x7F; ++L; | ||
|  | 		if(v <= 0x7FFFFFFFF) break sz; | ||
|  | 		usz[L-1] |= 0x80; usz[L] = ((v/0x10000) >>> 21) & 0x7F; ++L; | ||
|  | 		if(v <= 0x3FFFFFFFFFF) break sz; | ||
|  | 		usz[L-1] |= 0x80; usz[L] = ((v/0x1000000) >>> 21) & 0x7F; ++L; | ||
|  | 	} | ||
|  | 	return usz.slice(0, L); | ||
|  | } | ||
|  | export { write_varint49 }; | ||
|  | 
 | ||
|  | /** Parse a 32-bit signed integer from the raw varint */ | ||
|  | function varint_to_i32(buf: Uint8Array): number { | ||
|  | 	var l = 0, i32 = buf[l] & 0x7F; | ||
|  | 	varint: if(buf[l++] >= 0x80) { | ||
|  | 		i32 |= (buf[l] & 0x7F) <<  7; if(buf[l++] < 0x80) break varint; | ||
|  | 		i32 |= (buf[l] & 0x7F) << 14; if(buf[l++] < 0x80) break varint; | ||
|  | 		i32 |= (buf[l] & 0x7F) << 21; if(buf[l++] < 0x80) break varint; | ||
|  | 		i32 |= (buf[l] & 0x7F) << 28; | ||
|  | 	} | ||
|  | 	return i32; | ||
|  | } | ||
|  | export { varint_to_i32 }; | ||
|  | 
 | ||
|  | interface ProtoItem { | ||
|  | 	offset?: number; | ||
|  | 	data: Uint8Array; | ||
|  | 	type: number; | ||
|  | } | ||
|  | type ProtoField = Array<ProtoItem> | ||
|  | type ProtoMessage = Array<ProtoField>; | ||
|  | export { ProtoItem, ProtoField, ProtoMessage }; | ||
|  | /** Shallow parse of a message */ | ||
|  | function parse_shallow(buf: Uint8Array): ProtoMessage { | ||
|  | 	var out: ProtoMessage = [], ptr: Ptr = [0]; | ||
|  | 	while(ptr[0] < buf.length) { | ||
|  | 		var off = ptr[0]; | ||
|  | 		var num = parse_varint49(buf, ptr); | ||
|  | 		var type = num & 0x07; num = Math.floor(num / 8); | ||
|  | 		var len = 0; | ||
|  | 		var res: Uint8Array; | ||
|  | 		if(num == 0) break; | ||
|  | 		switch(type) { | ||
|  | 			case 0: { | ||
|  | 				var l = ptr[0]; | ||
|  | 				while(buf[ptr[0]++] >= 0x80); | ||
|  | 				res = buf.slice(l, ptr[0]); | ||
|  | 			} break; | ||
|  | 			case 5: len = 4; res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break; | ||
|  | 			case 1: len = 8; res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break; | ||
|  | 			case 2: len = parse_varint49(buf, ptr); res = buf.slice(ptr[0], ptr[0] + len); ptr[0] += len; break; | ||
|  | 			case 3: // Start group
 | ||
|  | 			case 4: // End group
 | ||
|  | 			default: throw new Error(`PB Type ${type} for Field ${num} at offset ${off}`); | ||
|  | 		} | ||
|  | 		var v: ProtoItem = { offset: off, data: res, type }; | ||
|  | 		if(out[num] == null) out[num] = [v]; | ||
|  | 		else out[num].push(v); | ||
|  | 	} | ||
|  | 	return out; | ||
|  | } | ||
|  | export { parse_shallow }; | ||
|  | /** Serialize a shallow parse */ | ||
|  | function write_shallow(proto: ProtoMessage): Uint8Array { | ||
|  | 	var out: Uint8Array[] = []; | ||
|  | 	proto.forEach((field, idx) => { | ||
|  | 		field.forEach(item => { | ||
|  | 			out.push(write_varint49(idx * 8 + item.type)); | ||
|  | 			out.push(item.data); | ||
|  | 		}); | ||
|  | 	}); | ||
|  | 	return u8concat(out); | ||
|  | } | ||
|  | export { write_shallow }; | ||
|  | 
 | ||
|  | function mappa<U>(data: ProtoField, cb:(Uint8Array) => U): U[] { | ||
|  | 	if(!data) return []; | ||
|  | 	return data.map((d) => { try { | ||
|  | 		return cb(d.data); | ||
|  | 	} catch(e) { | ||
|  | 		var m = e.message?.match(/at offset (\d+)/); | ||
|  | 		if(m) e.message = e.message.replace(/at offset (\d+)/, "at offset " + (+m[1] + d.offset)); | ||
|  | 		throw e; | ||
|  | 	}}); | ||
|  | } | ||
|  | export { mappa }; |