reflection.ts
1 import { equal } from "@std/assert"; 2 import type { CodecKey } from "./codec.ts"; 3 4 /** 5 * Get a value from an array or map given a `key`, which can be a string, number, or object. 6 * If the keys is an object then a deep equality check is performed while iterating through a map. 7 * TODO: Iterateing through the map to find a key/value is suboptimal, consider using a more efficient data structure. 8 */ 9 export function get( 10 obj: unknown, 11 key: CodecKey, 12 ) { 13 if (obj instanceof Map) { 14 if ( 15 typeof key === "object" && key !== null 16 ) { 17 // find the key in the map if the key is an array 18 const f = Array.from(obj.entries()).find(([k]) => equal(k, key)); 19 if (f) return f[1]; 20 } else { 21 return obj.get(key); 22 } 23 } else if ( 24 typeof obj === "object" && obj !== null && 25 (typeof key === "number" || 26 typeof key === "string") 27 ) { 28 return Reflect.get(obj, key); 29 } else { 30 // obj was a number / bool / null / undefined / etc 31 return undefined; 32 } 33 } 34 35 /** 36 * Set a value in an array or map given a `key`, which can be a string, number, or object. 37 */ 38 export function set( 39 obj: unknown, 40 key: CodecKey, 41 value: unknown, 42 ): void { 43 if (obj instanceof Map) { 44 const f = Array.from(obj.entries()).find(([k]) => equal(k, key)) ?? [key]; 45 obj.set(f[0], value); 46 } else if ( 47 typeof obj === "object" && obj !== null && 48 (typeof key === "number" || 49 typeof key === "string") 50 ) { 51 Reflect.set(obj, key, value); 52 } else { 53 throw new Error(`Cannot set key ${key} on ${obj}`); 54 } 55 } 56 57 /** 58 * Remove a value from an array or map given a `key`, which can be a string, number, or object. 59 */ 60 export function remove( 61 obj: unknown, 62 key: CodecKey, 63 ): void { 64 if (obj instanceof Map) { 65 const f = Array.from(obj.entries()).find(([k]) => equal(k, key)); 66 if (f) obj.delete(f[0]); 67 } else if ( 68 obj instanceof Array && typeof key === "number" 69 ) { 70 obj.splice(key, 1); 71 } else { 72 throw new Error(`Cannot remove key ${key} from ${obj}`); 73 } 74 }