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 };
 |