1 | function getLength(type, collection) {
|
2 | if (type === 'Object') {
|
3 |
|
4 | return Object.keys(collection).length;
|
5 | }
|
6 | else if (type === 'Array') {
|
7 | return collection.length;
|
8 | }
|
9 | return Infinity;
|
10 | }
|
11 | function isIterableMap(collection) {
|
12 | return typeof collection.set === 'function';
|
13 | }
|
14 | function getEntries(type, collection, sortObjectKeys, from = 0, to = Infinity) {
|
15 | let res;
|
16 | if (type === 'Object') {
|
17 | let keys = Object.getOwnPropertyNames(collection);
|
18 | if (sortObjectKeys) {
|
19 | keys.sort(sortObjectKeys === true ? undefined : sortObjectKeys);
|
20 | }
|
21 | keys = keys.slice(from, to + 1);
|
22 | res = {
|
23 | entries: keys.map((key) => ({ key, value: collection[key] })),
|
24 | };
|
25 | }
|
26 | else if (type === 'Array') {
|
27 | res = {
|
28 | entries: collection
|
29 | .slice(from, to + 1)
|
30 | .map((val, idx) => ({ key: idx + from, value: val })),
|
31 | };
|
32 | }
|
33 | else {
|
34 | let idx = 0;
|
35 | const entries = [];
|
36 | let done = true;
|
37 | const isMap = isIterableMap(collection);
|
38 | for (const item of collection) {
|
39 | if (idx > to) {
|
40 | done = false;
|
41 | break;
|
42 | }
|
43 | if (from <= idx) {
|
44 | if (isMap && Array.isArray(item)) {
|
45 | if (typeof item[0] === 'string' || typeof item[0] === 'number') {
|
46 | entries.push({ key: item[0], value: item[1] });
|
47 | }
|
48 | else {
|
49 | entries.push({
|
50 | key: `[entry ${idx}]`,
|
51 | value: {
|
52 | '[key]': item[0],
|
53 | '[value]': item[1],
|
54 | },
|
55 | });
|
56 | }
|
57 | }
|
58 | else {
|
59 | entries.push({ key: idx, value: item });
|
60 | }
|
61 | }
|
62 | idx++;
|
63 | }
|
64 | res = {
|
65 | hasMore: !done,
|
66 | entries,
|
67 | };
|
68 | }
|
69 | return res;
|
70 | }
|
71 | function getRanges(from, to, limit) {
|
72 | const ranges = [];
|
73 | while (to - from > limit * limit) {
|
74 | limit = limit * limit;
|
75 | }
|
76 | for (let i = from; i <= to; i += limit) {
|
77 | ranges.push({ from: i, to: Math.min(to, i + limit - 1) });
|
78 | }
|
79 | return ranges;
|
80 | }
|
81 | export default function getCollectionEntries(type, collection, sortObjectKeys, limit, from = 0, to = Infinity) {
|
82 | const getEntriesBound = getEntries.bind(null, type, collection, sortObjectKeys);
|
83 | if (!limit) {
|
84 | return getEntriesBound().entries;
|
85 | }
|
86 | const isSubset = to < Infinity;
|
87 | const length = Math.min(to - from, getLength(type, collection));
|
88 | if (type !== 'Iterable') {
|
89 | if (length <= limit || limit < 7) {
|
90 | return getEntriesBound(from, to).entries;
|
91 | }
|
92 | }
|
93 | else {
|
94 | if (length <= limit && !isSubset) {
|
95 | return getEntriesBound(from, to).entries;
|
96 | }
|
97 | }
|
98 | let limitedEntries;
|
99 | if (type === 'Iterable') {
|
100 | const { hasMore, entries } = getEntriesBound(from, from + limit - 1);
|
101 | limitedEntries = hasMore
|
102 | ? [...entries, ...getRanges(from + limit, from + 2 * limit - 1, limit)]
|
103 | : entries;
|
104 | }
|
105 | else {
|
106 | limitedEntries = isSubset
|
107 | ? getRanges(from, to, limit)
|
108 | : [
|
109 | ...getEntriesBound(0, limit - 5).entries,
|
110 | ...getRanges(limit - 4, length - 5, limit),
|
111 | ...getEntriesBound(length - 4, length - 1).entries,
|
112 | ];
|
113 | }
|
114 | return limitedEntries;
|
115 | }
|