Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | 3x 8x 3x 3x 3x 3x 3x 3x 5x 5x 10x 5x 3x 8x 8x 8x 8x 1x 8x 23x 23x 46x 23x 8x 17x 14x 1x 1x 1x 1x 14x 14x 5x 9x 8x 4x | import { isPlainObject, mapValues, range, shuffle } from 'lodash-uni' import { base64UrlDecode, base64UrlEncode } from './base64' import { isType } from './isType' import { rot13 } from './rot13' export type RawObjectData = Record<any, any> export type RawListData<TRawObjectData extends RawObjectData = RawObjectData> = TRawObjectData[] export type RawData<TRawObjectData extends RawObjectData = RawObjectData> = | TRawObjectData | RawListData<TRawObjectData> export type ElementOfRawData<TRawData extends RawData> = TRawData extends RawData<infer X> ? X : never export type KeyOfRawData<TRawData extends RawData> = keyof ElementOfRawData<TRawData> export type ValueOfRawData<TRawData extends RawData> = ElementOfRawData<TRawData>[KeyOfRawData<TRawData>] export type PackedData<TRawData extends RawData> = { readonly _k: Array<KeyOfRawData<TRawData>> readonly _v: Array<Array<ValueOfRawData<TRawData>>> readonly _s: string } /** * 数据打包器。 */ export class DataPacker { private static encodeIndexes(indexes: number[]): string { return rot13( base64UrlEncode( `${Math.random().toString(36).slice(2)}.${indexes.join('.')}`, ), ) } private static decodeIndexes(value: string): number[] { return base64UrlDecode(rot13(value)).split('.').slice(1).map(Number) } /** * 打包数据。 */ static pack<TRawObjectData extends RawData>( rawData: TRawObjectData, ): PackedData<TRawObjectData> { const notArray = !Array.isArray(rawData) const rawList: RawListData = notArray ? [rawData] : (rawData as any) const keys: Array<KeyOfRawData<TRawObjectData>> = rawList.length ? shuffle(Object.keys(rawList[0]) as any) : [] const indexes: number[] = shuffle(range(0, keys.length)) const values = [] for (const rawItem of rawList) { const item = [] for (let i = 0, len = indexes.length; i < len; i++) { item[indexes[i]] = rawItem[keys[i]] } values.push(item) } return { _k: keys, _v: values, _s: DataPacker.encodeIndexes(notArray ? [-1, ...indexes] : indexes), } } /** * 返回结果同 `pack()`,不过类型是原数据的类型。 */ static packAsRawType<T>(rawData: T): T { return DataPacker.pack(rawData as any) as any } /** * 解包数据。 */ static unpack<TRawObjectData extends RawData>( packedData: PackedData<TRawObjectData>, ): RawData<TRawObjectData> { const rawList: Array<RawListData<TRawObjectData>> = [] const indexes = DataPacker.decodeIndexes(packedData._s) const notArray = indexes[0] === -1 if (notArray) { indexes.shift() } for (const values of packedData._v) { const item: ElementOfRawData<TRawObjectData> = {} as any for (let i = 0, len = indexes.length; i < len; i++) { item[packedData._k[i]] = values[indexes[i]] } rawList.push(item) } return (notArray ? rawList[0] : rawList) as any } /** * 如果是打包后的数据,则解包后返回,否则直接返回。如果是对象,则递归尝试解包。 * * @param value 数据 * @param depth 递归层级,默认:2 * @returns 返回结果数据 */ static unpackIfNeeded(value: any, depth = 2): any { if (isPlainObject(value)) { // 兼容 v2 的 StructuredListTransformer 产生的数据 // https://github.com/fjc0k/vtils/blob/v2/packages/vtils/src/StructuredListTransformer.ts if (value.__IS_PACKED_STRUCTURED_LIST__) { value._k = value.keys value._v = value.values value._s = value.signature delete value.__IS_PACKED_STRUCTURED_LIST__ } if (isType<PackedData<RawObjectData>>(value)) { if (value._k && value._v && value._s) { return DataPacker.unpack(value) } if (depth > 0) { return mapValues(value, v => DataPacker.unpackIfNeeded(v, depth - 1)) } } } return value } } |