forked from sheetjs/sheetjs
		
	
		
			
	
	
		
			611 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			611 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 
								 | 
							
								#!/usr/bin/env -S deno run -A
							 | 
						||
| 
								 | 
							
								/*! otorp (C) 2021-present SheetJS -- http://sheetjs.com */
							 | 
						||
| 
								 | 
							
								import { resolve } from "https://deno.land/std@0.171.0/path/mod.ts";
							 | 
						||
| 
								 | 
							
								import { TerminalSpinner } from "https://deno.land/x/spinners/mod.ts";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #region util.ts
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var u8_to_dataview = (array: Uint8Array): DataView => new DataView(array.buffer, array.byteOffset, array.byteLength);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var u8str = (u8: Uint8Array): string => new TextDecoder().decode(u8);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var u8concat = (u8a: Uint8Array[]): Uint8Array => {
							 | 
						||
| 
								 | 
							
								  var len = u8a.reduce((acc: number, x: Uint8Array) => acc + x.length, 0);
							 | 
						||
| 
								 | 
							
								  var out = new Uint8Array(len);
							 | 
						||
| 
								 | 
							
								  var off = 0;
							 | 
						||
| 
								 | 
							
								  u8a.forEach(u8 => { out.set(u8, off); off += u8.length; });
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var indent = (str: string, depth: number /* = 1 */): string => str.split(/\n/g).map(x => x && "  ".repeat(depth) + x).join("\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function u8indexOf(u8: Uint8Array, data: string | number | Uint8Array, byteOffset?: number): number {
							 | 
						||
| 
								 | 
							
								  //if(Buffer.isBuffer(u8)) return u8.indexOf(data, byteOffset);
							 | 
						||
| 
								 | 
							
								  if(typeof data == "number") return u8.indexOf(data, byteOffset);
							 | 
						||
| 
								 | 
							
								  var l = byteOffset;
							 | 
						||
| 
								 | 
							
								  if(typeof data == "string") {
							 | 
						||
| 
								 | 
							
								    outs: while((l = u8.indexOf(data.charCodeAt(0), l)) > -1) {
							 | 
						||
| 
								 | 
							
								      ++l;
							 | 
						||
| 
								 | 
							
								      for(var j = 1; j < data.length; ++j) if(u8[l+j-1] != data.charCodeAt(j)) continue outs;
							 | 
						||
| 
								 | 
							
								      return l - 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    outb: while((l = u8.indexOf(data[0], l)) > -1) {
							 | 
						||
| 
								 | 
							
								      ++l;
							 | 
						||
| 
								 | 
							
								      for(var j = 1; j < data.length; ++j) if(u8[l+j-1] != data[j]) continue outb;
							 | 
						||
| 
								 | 
							
								      return l - 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return -1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #endregion
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #region proto.ts
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type Ptr = [number];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** 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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** 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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface ProtoItem {
							 | 
						||
| 
								 | 
							
								  offset?: number;
							 | 
						||
| 
								 | 
							
								  data: Uint8Array;
							 | 
						||
| 
								 | 
							
								  type: number;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								type ProtoField = Array<ProtoItem>
							 | 
						||
| 
								 | 
							
								type ProtoMessage = Array<ProtoField>;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** 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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** 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);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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||0)));
							 | 
						||
| 
								 | 
							
								    throw e;
							 | 
						||
| 
								 | 
							
								  }});
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #endregion
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #region descriptor.ts
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var TYPES = [
							 | 
						||
| 
								 | 
							
								  "error",
							 | 
						||
| 
								 | 
							
								  "double",
							 | 
						||
| 
								 | 
							
								  "float",
							 | 
						||
| 
								 | 
							
								  "int64",
							 | 
						||
| 
								 | 
							
								  "uint64",
							 | 
						||
| 
								 | 
							
								  "int32",
							 | 
						||
| 
								 | 
							
								  "fixed64",
							 | 
						||
| 
								 | 
							
								  "fixed32",
							 | 
						||
| 
								 | 
							
								  "bool",
							 | 
						||
| 
								 | 
							
								  "string",
							 | 
						||
| 
								 | 
							
								  "group",
							 | 
						||
| 
								 | 
							
								  "message",
							 | 
						||
| 
								 | 
							
								  "bytes",
							 | 
						||
| 
								 | 
							
								  "uint32",
							 | 
						||
| 
								 | 
							
								  "enum",
							 | 
						||
| 
								 | 
							
								  "sfixed32",
							 | 
						||
| 
								 | 
							
								  "sfixed64",
							 | 
						||
| 
								 | 
							
								  "sint32",
							 | 
						||
| 
								 | 
							
								  "sint64"
							 | 
						||
| 
								 | 
							
								];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface FileOptions {
							 | 
						||
| 
								 | 
							
								  javaPackage?: string;
							 | 
						||
| 
								 | 
							
								  javaOuterClassname?: string;
							 | 
						||
| 
								 | 
							
								  javaMultipleFiles?: string;
							 | 
						||
| 
								 | 
							
								  goPackage?: string;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function parse_FileOptions(buf: Uint8Array): FileOptions {
							 | 
						||
| 
								 | 
							
								  var data = parse_shallow(buf);
							 | 
						||
| 
								 | 
							
								  var out: FileOptions = {};
							 | 
						||
| 
								 | 
							
								  if(data[1]?.[0]) out.javaPackage = u8str(data[1][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[8]?.[0]) out.javaOuterClassname = u8str(data[8][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[11]?.[0]) out.goPackage = u8str(data[11][0].data);
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface EnumValue {
							 | 
						||
| 
								 | 
							
								  name?: string;
							 | 
						||
| 
								 | 
							
								  number?: number;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function parse_EnumValue(buf: Uint8Array): EnumValue {
							 | 
						||
| 
								 | 
							
								  var data = parse_shallow(buf);
							 | 
						||
| 
								 | 
							
								  var out: EnumValue = {};
							 | 
						||
| 
								 | 
							
								  if(data[1]?.[0]) out.name = u8str(data[1][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[2]?.[0]) out.number = varint_to_i32(data[2][0].data);
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface Enum {
							 | 
						||
| 
								 | 
							
								  name?: string;
							 | 
						||
| 
								 | 
							
								  value?: EnumValue[];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function parse_Enum(buf: Uint8Array): Enum {
							 | 
						||
| 
								 | 
							
								  var data = parse_shallow(buf);
							 | 
						||
| 
								 | 
							
								  var out: Enum = {};
							 | 
						||
| 
								 | 
							
								  if(data[1]?.[0]) out.name = u8str(data[1][0].data);
							 | 
						||
| 
								 | 
							
								  out.value = mappa(data[2], parse_EnumValue);
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								var write_Enum = (en: Enum): string => {
							 | 
						||
| 
								 | 
							
								  var out = [`enum ${en.name} {`];
							 | 
						||
| 
								 | 
							
								  en.value?.forEach(({name, number}) => out.push(`  ${name} = ${number};`));
							 | 
						||
| 
								 | 
							
								  return out.concat(`}`).join("\n");
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface FieldOptions {
							 | 
						||
| 
								 | 
							
								  packed?: boolean;
							 | 
						||
| 
								 | 
							
								  deprecated?: boolean;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function parse_FieldOptions(buf: Uint8Array): FieldOptions {
							 | 
						||
| 
								 | 
							
								  var data = parse_shallow(buf);
							 | 
						||
| 
								 | 
							
								  var out: FieldOptions = {};
							 | 
						||
| 
								 | 
							
								  if(data[2]?.[0]) out.packed = !!data[2][0].data;
							 | 
						||
| 
								 | 
							
								  if(data[3]?.[0]) out.deprecated = !!data[3][0].data;
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface Field {
							 | 
						||
| 
								 | 
							
								  name?: string;
							 | 
						||
| 
								 | 
							
								  extendee?: string;
							 | 
						||
| 
								 | 
							
								  number?: number;
							 | 
						||
| 
								 | 
							
								  label?: number;
							 | 
						||
| 
								 | 
							
								  type?: number;
							 | 
						||
| 
								 | 
							
								  typeName?: string;
							 | 
						||
| 
								 | 
							
								  defaultValue?: string;
							 | 
						||
| 
								 | 
							
								  options?: FieldOptions;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function parse_Field(buf: Uint8Array): Field {
							 | 
						||
| 
								 | 
							
								  var data = parse_shallow(buf);
							 | 
						||
| 
								 | 
							
								  var out: Field = {};
							 | 
						||
| 
								 | 
							
								  if(data[1]?.[0]) out.name = u8str(data[1][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[2]?.[0]) out.extendee = u8str(data[2][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[3]?.[0]) out.number = varint_to_i32(data[3][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[4]?.[0]) out.label = varint_to_i32(data[4][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[5]?.[0]) out.type = varint_to_i32(data[5][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[6]?.[0]) out.typeName = u8str(data[6][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[7]?.[0]) out.defaultValue = u8str(data[7][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[8]?.[0]) out.options = parse_FieldOptions(data[8][0].data);
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function write_Field(field: Field): string {
							 | 
						||
| 
								 | 
							
								  var out = [];
							 | 
						||
| 
								 | 
							
								  var label = ["", "optional ", "required ", "repeated "][field.label||0] || "";
							 | 
						||
| 
								 | 
							
								  var type = field.typeName || TYPES[field.type||69] || "s5s";
							 | 
						||
| 
								 | 
							
								  var opts = [];
							 | 
						||
| 
								 | 
							
								  if(field.defaultValue) opts.push(`default = ${field.defaultValue}`);
							 | 
						||
| 
								 | 
							
								  if(field.options?.packed) opts.push(`packed = true`);
							 | 
						||
| 
								 | 
							
								  if(field.options?.deprecated) opts.push(`deprecated = true`);
							 | 
						||
| 
								 | 
							
								  var os = opts.length ? ` [${opts.join(", ")}]`: "";
							 | 
						||
| 
								 | 
							
								  out.push(`${label}${type} ${field.name} = ${field.number}${os};`);
							 | 
						||
| 
								 | 
							
								  return out.length ? indent(out.join("\n"), 1) : "";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function write_extensions(ext: Field[], xtra = false, coalesce = true): string {
							 | 
						||
| 
								 | 
							
								  var res: string[] = [];
							 | 
						||
| 
								 | 
							
								  var xt: Array<[string, Array<Field>]> = [];
							 | 
						||
| 
								 | 
							
								  ext.forEach(ext => {
							 | 
						||
| 
								 | 
							
								    if(!ext.extendee) return;
							 | 
						||
| 
								 | 
							
								    var row = coalesce ?
							 | 
						||
| 
								 | 
							
								      xt.find(x => x[0] == ext.extendee) :
							 | 
						||
| 
								 | 
							
								      (xt[xt.length - 1]?.[0] == ext.extendee ? xt[xt.length - 1]: null);
							 | 
						||
| 
								 | 
							
								    if(row) row[1].push(ext);
							 | 
						||
| 
								 | 
							
								    else xt.push([ext.extendee, [ext]]);
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  xt.forEach(extrow => {
							 | 
						||
| 
								 | 
							
								    var out = [`extend ${extrow[0]} {`];
							 | 
						||
| 
								 | 
							
								    extrow[1].forEach(ext => out.push(write_Field(ext)));
							 | 
						||
| 
								 | 
							
								    res.push(out.concat(`}`).join("\n") + (xtra ? "\n" : ""));
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  return res.join("\n");
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface ExtensionRange { start?: number; end?: number; }
							 | 
						||
| 
								 | 
							
								interface MessageType {
							 | 
						||
| 
								 | 
							
								  name?: string;
							 | 
						||
| 
								 | 
							
								  nestedType?: MessageType[];
							 | 
						||
| 
								 | 
							
								  enumType?: Enum[];
							 | 
						||
| 
								 | 
							
								  field?: Field[];
							 | 
						||
| 
								 | 
							
								  extension?: Field[];
							 | 
						||
| 
								 | 
							
								  extensionRange?: ExtensionRange[];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function parse_mtype(buf: Uint8Array): MessageType {
							 | 
						||
| 
								 | 
							
								  var data = parse_shallow(buf);
							 | 
						||
| 
								 | 
							
								  var out: MessageType = {};
							 | 
						||
| 
								 | 
							
								  if(data[1]?.[0]) out.name = u8str(data[1][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[2]?.length >= 1) out.field = mappa(data[2], parse_Field);
							 | 
						||
| 
								 | 
							
								  if(data[3]?.length >= 1) out.nestedType = mappa(data[3], parse_mtype);
							 | 
						||
| 
								 | 
							
								  if(data[4]?.length >= 1) out.enumType = mappa(data[4], parse_Enum);
							 | 
						||
| 
								 | 
							
								  if(data[6]?.length >= 1) out.extension = mappa(data[6], parse_Field);
							 | 
						||
| 
								 | 
							
								  if(data[5]?.length >= 1) out.extensionRange = data[5].map(d => {
							 | 
						||
| 
								 | 
							
								    var data = parse_shallow(d.data);
							 | 
						||
| 
								 | 
							
								    var out: ExtensionRange = {};
							 | 
						||
| 
								 | 
							
								    if(data[1]?.[0]) out.start = varint_to_i32(data[1][0].data);
							 | 
						||
| 
								 | 
							
								    if(data[2]?.[0]) out.end   = varint_to_i32(data[2][0].data);
							 | 
						||
| 
								 | 
							
								    return out;
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								var write_mtype = (message: MessageType): string => {
							 | 
						||
| 
								 | 
							
								  var out = [ `message ${message.name} {` ];
							 | 
						||
| 
								 | 
							
								  message.nestedType?.forEach(m => out.push(indent(write_mtype(m), 1)));
							 | 
						||
| 
								 | 
							
								  message.enumType?.forEach(en => out.push(indent(write_Enum(en), 1)));
							 | 
						||
| 
								 | 
							
								  message.field?.forEach(field => out.push(write_Field(field)));
							 | 
						||
| 
								 | 
							
								  if(message.extensionRange) message.extensionRange.forEach(er => out.push(`  extensions ${er.start} to ${(er.end||0) - 1};`));
							 | 
						||
| 
								 | 
							
								  if(message.extension?.length) out.push(indent(write_extensions(message.extension), 1));
							 | 
						||
| 
								 | 
							
								  return out.concat(`}`).join("\n");
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface Descriptor {
							 | 
						||
| 
								 | 
							
								  name?: string;
							 | 
						||
| 
								 | 
							
								  package?: string;
							 | 
						||
| 
								 | 
							
								  dependency?: string[];
							 | 
						||
| 
								 | 
							
								  messageType?: MessageType[];
							 | 
						||
| 
								 | 
							
								  enumType?: Enum[];
							 | 
						||
| 
								 | 
							
								  extension?: Field[];
							 | 
						||
| 
								 | 
							
								  options?: FileOptions;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function parse_FileDescriptor(buf: Uint8Array): Descriptor {
							 | 
						||
| 
								 | 
							
								  var data = parse_shallow(buf);
							 | 
						||
| 
								 | 
							
								  var out: Descriptor = {};
							 | 
						||
| 
								 | 
							
								  if(data[1]?.[0]) out.name = u8str(data[1][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[2]?.[0]) out.package = u8str(data[2][0].data);
							 | 
						||
| 
								 | 
							
								  if(data[3]?.[0]) out.dependency = data[3].map(x => u8str(x.data));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if(data[4]?.length >= 1) out.messageType = mappa(data[4], parse_mtype);
							 | 
						||
| 
								 | 
							
								  if(data[5]?.length >= 1) out.enumType = mappa(data[5], parse_Enum);
							 | 
						||
| 
								 | 
							
								  if(data[7]?.length >= 1) out.extension = mappa(data[7], parse_Field);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if(data[8]?.[0]) out.options = parse_FileOptions(data[8][0].data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								var write_FileDescriptor = (pb: Descriptor): string => {
							 | 
						||
| 
								 | 
							
								  var out = [
							 | 
						||
| 
								 | 
							
								    'syntax = "proto2";',
							 | 
						||
| 
								 | 
							
								    ''
							 | 
						||
| 
								 | 
							
								  ];
							 | 
						||
| 
								 | 
							
								  if(pb.dependency) pb.dependency.forEach((n: string) => { if(n) out.push(`import "${n}";`); });
							 | 
						||
| 
								 | 
							
								  if(pb.package) out.push(`package ${pb.package};\n`);
							 | 
						||
| 
								 | 
							
								  if(pb.options) {
							 | 
						||
| 
								 | 
							
								    var o = out.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(pb.options.javaPackage) out.push(`option java_package = "${pb.options.javaPackage}";`);
							 | 
						||
| 
								 | 
							
								    if(pb.options.javaOuterClassname?.replace(/\W/g, "")) out.push(`option java_outer_classname = "${pb.options.javaOuterClassname}";`);
							 | 
						||
| 
								 | 
							
								    if(pb.options.javaMultipleFiles) out.push(`option java_multiple_files = true;`);
							 | 
						||
| 
								 | 
							
								    if(pb.options.goPackage) out.push(`option go_package = "${pb.options.goPackage}";`);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(out.length > o) out.push('');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pb.enumType?.forEach(en => { if(en.name) out.push(write_Enum(en) + "\n"); });
							 | 
						||
| 
								 | 
							
								  pb.messageType?.forEach(m => { if(m.name) { var o = write_mtype(m); if(o) out.push(o + "\n"); }});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if(pb.extension?.length) {
							 | 
						||
| 
								 | 
							
								    var e = write_extensions(pb.extension, true, false);
							 | 
						||
| 
								 | 
							
								    if(e) out.push(e);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return out.join("\n") + "\n";
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #endregion
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #region macho.ts
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface MachOEntry {
							 | 
						||
| 
								 | 
							
								  type: number;
							 | 
						||
| 
								 | 
							
								  subtype: number;
							 | 
						||
| 
								 | 
							
								  offset: number;
							 | 
						||
| 
								 | 
							
								  size: number;
							 | 
						||
| 
								 | 
							
								  align?: number;
							 | 
						||
| 
								 | 
							
								  data: Uint8Array;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								var parse_fat = (buf: Uint8Array): MachOEntry[] => {
							 | 
						||
| 
								 | 
							
								  var dv = u8_to_dataview(buf);
							 | 
						||
| 
								 | 
							
								  if(dv.getUint32(0, false) !== 0xCAFEBABE) throw new Error("Unsupported file");
							 | 
						||
| 
								 | 
							
								  var nfat_arch = dv.getUint32(4, false);
							 | 
						||
| 
								 | 
							
								  var out: MachOEntry[] = [];
							 | 
						||
| 
								 | 
							
								  for(var i = 0; i < nfat_arch; ++i) {
							 | 
						||
| 
								 | 
							
								    var start = i * 20 + 8;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var cputype = dv.getUint32(start, false);
							 | 
						||
| 
								 | 
							
								    var cpusubtype = dv.getUint32(start+4, false);
							 | 
						||
| 
								 | 
							
								    var offset = dv.getUint32(start+8, false);
							 | 
						||
| 
								 | 
							
								    var size = dv.getUint32(start+12, false);
							 | 
						||
| 
								 | 
							
								    var align = dv.getUint32(start+16, false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    out.push({
							 | 
						||
| 
								 | 
							
								      type: cputype,
							 | 
						||
| 
								 | 
							
								      subtype: cpusubtype,
							 | 
						||
| 
								 | 
							
								      offset,
							 | 
						||
| 
								 | 
							
								      size,
							 | 
						||
| 
								 | 
							
								      align,
							 | 
						||
| 
								 | 
							
								      data: buf.slice(offset, offset + size)
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								var parse_macho = (buf: Uint8Array): MachOEntry[] => {
							 | 
						||
| 
								 | 
							
								  var dv = u8_to_dataview(buf);
							 | 
						||
| 
								 | 
							
								  var magic = dv.getUint32(0, false);
							 | 
						||
| 
								 | 
							
								  switch(magic) {
							 | 
						||
| 
								 | 
							
								    // fat binary (x86_64 / aarch64)
							 | 
						||
| 
								 | 
							
								    case 0xCAFEBABE: return parse_fat(buf);
							 | 
						||
| 
								 | 
							
								    // x86_64
							 | 
						||
| 
								 | 
							
								    case 0xCFFAEDFE: return [{
							 | 
						||
| 
								 | 
							
								      type: dv.getUint32(4, false),
							 | 
						||
| 
								 | 
							
								      subtype: dv.getUint32(8, false),
							 | 
						||
| 
								 | 
							
								      offset: 0,
							 | 
						||
| 
								 | 
							
								      size: buf.length,
							 | 
						||
| 
								 | 
							
								      data: buf
							 | 
						||
| 
								 | 
							
								    }];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  throw new Error("Unsupported file");
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #endregion
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #region otorp.ts
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								interface OtorpEntry {
							 | 
						||
| 
								 | 
							
								  name: string;
							 | 
						||
| 
								 | 
							
								  proto: string;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Find and stringify all relevant protobuf defs */
							 | 
						||
| 
								 | 
							
								function otorp(buf: Uint8Array, builtins = false): OtorpEntry[] {
							 | 
						||
| 
								 | 
							
								  var res = proto_offsets(buf);
							 | 
						||
| 
								 | 
							
								  var registry: {[key: string]: Descriptor} = {};
							 | 
						||
| 
								 | 
							
								  var names: Set<string> = new Set();
							 | 
						||
| 
								 | 
							
								  var out: OtorpEntry[] = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  res.forEach((r, i) => {
							 | 
						||
| 
								 | 
							
								    if(!builtins && r[1].startsWith("google/protobuf/")) return;
							 | 
						||
| 
								 | 
							
								    var b = buf.slice(r[0], i < res.length - 1 ? res[i+1][0] : buf.length);
							 | 
						||
| 
								 | 
							
								    var pb = parse_FileDescriptorProto(b/*, r[1]*/);
							 | 
						||
| 
								 | 
							
								    names.add(r[1]);
							 | 
						||
| 
								 | 
							
								    registry[r[1]] = pb;
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  names.forEach(name => {
							 | 
						||
| 
								 | 
							
								    /* ensure partial ordering by dependencies */
							 | 
						||
| 
								 | 
							
								    names.delete(name);
							 | 
						||
| 
								 | 
							
								    var pb = registry[name];
							 | 
						||
| 
								 | 
							
								    var doit = (pb.dependency||[]).every((d: string) => !names.has(d));
							 | 
						||
| 
								 | 
							
								    if(!doit) { names.add(name); return; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var dups = res.filter(r => r[1] == name);
							 | 
						||
| 
								 | 
							
								    if(dups.length == 1) return out.push({ name, proto: write_FileDescriptor(pb) });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* in a fat binary, compare the defs for x86_64/aarch64 */
							 | 
						||
| 
								 | 
							
								    var pbs = dups.map(r => {
							 | 
						||
| 
								 | 
							
								      var i = res.indexOf(r);
							 | 
						||
| 
								 | 
							
								      var b = buf.slice(r[0], i < res.length - 1 ? res[i+1][0] : buf.length);
							 | 
						||
| 
								 | 
							
								      var pb = parse_FileDescriptorProto(b/*, r[1]*/);
							 | 
						||
| 
								 | 
							
								      return write_FileDescriptor(pb);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    for(var l = 1; l < pbs.length; ++l) if(pbs[l] != pbs[0]) throw new Error(`Conflicting definitions for ${name} at offsets 0x${dups[0][0].toString(16)} and 0x${dups[l][0].toString(16)}`);
							 | 
						||
| 
								 | 
							
								    return out.push({ name, proto: pbs[0] });
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								export default otorp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Determine if an address is being referenced */
							 | 
						||
| 
								 | 
							
								var is_referenced = (buf: Uint8Array, pos: number): boolean => {
							 | 
						||
| 
								 | 
							
								  var dv = u8_to_dataview(buf);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Search for LEA reference (x86) */
							 | 
						||
| 
								 | 
							
								  for(var leaddr = 0; leaddr > -1 && leaddr < pos; leaddr = u8indexOf(buf, 0x8D, leaddr + 1))
							 | 
						||
| 
								 | 
							
								    if(dv.getUint32(leaddr + 2, true) == pos - leaddr - 6) return true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Search for absolute reference to address */
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    var headers = parse_macho(buf);
							 | 
						||
| 
								 | 
							
								    for(var i = 0; i < headers.length; ++i) {
							 | 
						||
| 
								 | 
							
								      if(pos < headers[i].offset || pos > headers[i].offset + headers[i].size) continue;
							 | 
						||
| 
								 | 
							
								      var b = headers[i].data;
							 | 
						||
| 
								 | 
							
								      var p = pos - headers[i].offset;
							 | 
						||
| 
								 | 
							
								      var ref = new Uint8Array([0,0,0,0,0,0,0,0]);
							 | 
						||
| 
								 | 
							
								      var dv = u8_to_dataview(ref);
							 | 
						||
| 
								 | 
							
								      dv.setUint32(0, p, true);
							 | 
						||
| 
								 | 
							
								      if(u8indexOf(b, ref, 0) > 0) return true;
							 | 
						||
| 
								 | 
							
								      ref[4] = 0x01;
							 | 
						||
| 
								 | 
							
								      if(u8indexOf(b, ref, 0) > 0) return true;
							 | 
						||
| 
								 | 
							
								      ref[4] = 0x00; ref[6] = 0x10;
							 | 
						||
| 
								 | 
							
								      if(u8indexOf(b, ref, 0) > 0) return true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } catch(e) {throw e}
							 | 
						||
| 
								 | 
							
								  return false;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type OffsetList = Array<[number, string, number, number]>;
							 | 
						||
| 
								 | 
							
								/** Generate a list of potential starting points */
							 | 
						||
| 
								 | 
							
								var proto_offsets = (buf: Uint8Array): OffsetList => {
							 | 
						||
| 
								 | 
							
								  var meta = parse_macho(buf);
							 | 
						||
| 
								 | 
							
								  var out: OffsetList = [];
							 | 
						||
| 
								 | 
							
								  var off = 0;
							 | 
						||
| 
								 | 
							
								  /* note: this loop only works for names < 128 chars */
							 | 
						||
| 
								 | 
							
								  search: while((off = u8indexOf(buf, ".proto", off + 1)) > -1) {
							 | 
						||
| 
								 | 
							
								    var pos = off;
							 | 
						||
| 
								 | 
							
								    off += 6;
							 | 
						||
| 
								 | 
							
								    while(off - pos < 256 && buf[pos] != off - pos - 1) {
							 | 
						||
| 
								 | 
							
								      if(buf[pos] > 0x7F || buf[pos] < 0x20) continue search;
							 | 
						||
| 
								 | 
							
								      --pos;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if(off - pos > 250) continue;
							 | 
						||
| 
								 | 
							
								    var name = u8str(buf.slice(pos + 1, off));
							 | 
						||
| 
								 | 
							
								    if(buf[--pos] != 0x0A) continue;
							 | 
						||
| 
								 | 
							
								    if(!is_referenced(buf, pos)) { console.error(`Reference to ${name} at ${pos} not found`); continue; }
							 | 
						||
| 
								 | 
							
								    var bin = meta.find(m => m.offset <= pos && m.offset + m.size >= pos);
							 | 
						||
| 
								 | 
							
								    out.push([pos, name, bin?.type || -1, bin?.subtype || -1]);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** Parse a descriptor that starts with the first byte of the supplied buffer */
							 | 
						||
| 
								 | 
							
								var parse_FileDescriptorProto = (buf: Uint8Array): Descriptor => {
							 | 
						||
| 
								 | 
							
								  var l = buf.length;
							 | 
						||
| 
								 | 
							
								  while(l > 0) try {
							 | 
						||
| 
								 | 
							
								    var b = buf.slice(0,l);
							 | 
						||
| 
								 | 
							
								    var o = parse_FileDescriptor(b);
							 | 
						||
| 
								 | 
							
								    return o;
							 | 
						||
| 
								 | 
							
								  } catch(e) {
							 | 
						||
| 
								 | 
							
								    var m = e.message.match(/at offset (\d+)/);
							 | 
						||
| 
								 | 
							
								    if(m && parseInt(m[1], 10) < buf.length) l = parseInt(m[1], 10) - 1;
							 | 
						||
| 
								 | 
							
								    else --l;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  throw new RangeError("no protobuf message in range");
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// #endregion
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let spin: TerminalSpinner;
							 | 
						||
| 
								 | 
							
								const width = Deno.consoleSize().columns;
							 | 
						||
| 
								 | 
							
								function process(inf: string, outf: string) {
							 | 
						||
| 
								 | 
							
								  const fi = Deno.statSync(inf);
							 | 
						||
| 
								 | 
							
								  if(fi.isDirectory) for(let info of Deno.readDirSync(inf)) {
							 | 
						||
| 
								 | 
							
								    if(spin) spin.set(inf.length > width - 4 ? "…" + inf.slice(-(width-4)) : inf);
							 | 
						||
| 
								 | 
							
								    process(inf + (inf.slice(-1) == "/" ? "" : "/") + info.name, outf);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    const buf: Uint8Array = Deno.readFileSync(inf);
							 | 
						||
| 
								 | 
							
								    var dv = u8_to_dataview(buf);
							 | 
						||
| 
								 | 
							
								    var magic = dv.getUint32(0, false);
							 | 
						||
| 
								 | 
							
								    if(![0xCAFEBABE, 0xCFFAEDFE].includes(magic)) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    otorp(buf).forEach(({name, proto}) => {
							 | 
						||
| 
								 | 
							
								      if(!outf) return console.log(proto);
							 | 
						||
| 
								 | 
							
								      var pth = resolve(outf || "./", name.replace(/[/]/g, "$"));
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        const str = Deno.readTextFileSync(pth);
							 | 
						||
| 
								 | 
							
								        if(str == proto) return;
							 | 
						||
| 
								 | 
							
								        throw `${pth} definition diverges!`;
							 | 
						||
| 
								 | 
							
								      } catch(e) { if(typeof e == "string") throw e; }
							 | 
						||
| 
								 | 
							
								      console.error(`writing ${name} to ${pth}`);
							 | 
						||
| 
								 | 
							
								      Deno.writeTextFileSync(pth, proto);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } catch(e) {}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function doit() {
							 | 
						||
| 
								 | 
							
								  const [ inf, outf ] = Deno.args;
							 | 
						||
| 
								 | 
							
								  if(!inf || inf == "-h" || inf == "--help") {
							 | 
						||
| 
								 | 
							
								    console.log(`usage: otorp.ts <path/to/bin> [output/folder]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if no output folder specified, log all discovered defs
							 | 
						||
| 
								 | 
							
								if output folder specified, attempt to write defs in the folder
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								$ otorp.ts /Applications/Numbers.app out/                   # search all files
							 | 
						||
| 
								 | 
							
								$ otorp.ts /Applications/Numbers.app/Contents/MacOS/Numbers # search one file
							 | 
						||
| 
								 | 
							
								`);
							 | 
						||
| 
								 | 
							
								    Deno.exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if(Deno.statSync(inf).isDirectory) (spin = new TerminalSpinner("")).start();
							 | 
						||
| 
								 | 
							
								  if(outf) try { Deno.mkdirSync(outf, { recursive: true }); } catch(e) {}
							 | 
						||
| 
								 | 
							
								  process(inf, outf);
							 | 
						||
| 
								 | 
							
								  if(spin) spin.stop();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								doit();
							 |