2.9 KB113 lines
Blame
1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8import type {List, Seq} from 'immutable';
9import type {Hash} from '../types';
10
11import {OrderedSet as ImSet} from 'immutable';
12import {SelfUpdate} from 'shared/immutableExt';
13
14/**
15 * Set of commit hashes, with extra methods.
16 * Internally maintains the order of the hashes information.
17 */
18export class HashSet extends SelfUpdate<ImSet<Hash>> {
19 constructor(set?: ImSet<Hash>) {
20 super(set ?? ImSet());
21 }
22
23 static fromHashes(hashes: SetLike): HashSet {
24 if (hashes == null) {
25 return new HashSet(ImSet());
26 } else if (hashes instanceof HashSet) {
27 return hashes;
28 } else if (typeof hashes === 'string') {
29 return new HashSet(ImSet([hashes]));
30 } else if (ImSet.isOrderedSet(hashes)) {
31 return new HashSet(hashes as ImSet<Hash>);
32 } else {
33 return new HashSet(ImSet(hashes));
34 }
35 }
36
37 toHashes(): ImSet<Hash> {
38 return this.set;
39 }
40
41 toSeq(): Seq.Set<Hash> {
42 return this.set.toSeq();
43 }
44
45 toList(): List<Hash> {
46 return this.set.toList();
47 }
48
49 toArray(): Array<Hash> {
50 return this.set.toArray();
51 }
52
53 /** Union with another set. Preserves the order: this, then other without the overlapping subset. */
54 union(other: SetLike): HashSet {
55 const set = this.set.union(HashSet.fromHashes(other).set);
56 return new HashSet(set);
57 }
58
59 /** Interset with another set. Preserves the order of `this` set. */
60 intersect(other: SetLike): HashSet {
61 const set = this.set.intersect(HashSet.fromHashes(other).set);
62 return new HashSet(set);
63 }
64
65 /** Remove items that exist in another set. Preserves the order of the `this` set. */
66 subtract(other: SetLike): HashSet {
67 const set = this.set.subtract(HashSet.fromHashes(other).set);
68 return new HashSet(set);
69 }
70
71 /** Test if this set contains the given hash. */
72 contains(hash: Hash): boolean {
73 return this.set.has(hash);
74 }
75
76 /** Reverse the order of the set. */
77 reverse(): HashSet {
78 return new HashSet(this.inner.reverse());
79 }
80
81 /** Convert to sorted array. Mainly for testing. */
82 toSortedArray(): Array<Hash> {
83 return this.set.toArray().sort();
84 }
85
86 [Symbol.iterator](): IterableIterator<Hash> {
87 return this.set[Symbol.iterator]();
88 }
89
90 get size(): number {
91 return this.set.size;
92 }
93
94 private get set(): ImSet<Hash> {
95 return this.inner;
96 }
97}
98
99export function arrayFromHashes(hashes: SetLike): Array<Hash> {
100 if (hashes == null) {
101 return [];
102 } else if (hashes instanceof HashSet) {
103 return hashes.toArray();
104 } else if (typeof hashes === 'string') {
105 return [hashes];
106 } else {
107 return [...hashes];
108 }
109}
110
111/** A convenient type that converts to HashSet. `null` converts to an empty set. */
112export type SetLike = HashSet | ImSet<Hash> | Iterable<Hash> | Hash | null | undefined;
113