IsSubsetOfElements returns true iff a multiset sub represents a subset of multiset super under equality given by eq. Signature of eq must be func(A, B) bool, where A, B are types, which elements of sub and super can be assigned to respectively. It panics if either sub or super is not one of: 1. stri
(eq any, sub, super any)
| 136 | // 2. value, which implements Ranger interface(e.g. sync.Map) |
| 137 | // NOTE: Map key values are not taken into account. |
| 138 | func IsSubsetOfElements(eq any, sub, super any) bool { |
| 139 | if sub == nil { |
| 140 | // NOTE: Empty set is a subset of any set. |
| 141 | return true |
| 142 | } |
| 143 | if super == nil { |
| 144 | // NOTE: No non-empty set is a subset of empty set. |
| 145 | return false |
| 146 | } |
| 147 | |
| 148 | ev := reflect.ValueOf(eq) |
| 149 | if ev.Kind() != reflect.Func { |
| 150 | panic(fmt.Errorf("expected kind of eq to be a function, got: %s", ev.Kind())) |
| 151 | } |
| 152 | subR, ok := WrapRanger(sub) |
| 153 | if !ok { |
| 154 | panic(fmt.Errorf("cannot range over values of type %T", sub)) |
| 155 | } |
| 156 | supR, ok := WrapRanger(super) |
| 157 | if !ok { |
| 158 | panic(fmt.Errorf("cannot range over values of type %T", super)) |
| 159 | } |
| 160 | |
| 161 | type entry struct { |
| 162 | value reflect.Value |
| 163 | found uint |
| 164 | } |
| 165 | entries := map[*entry]struct{}{} |
| 166 | |
| 167 | findEntry := func(v reflect.Value) *entry { |
| 168 | for e := range entries { |
| 169 | if ev.Call([]reflect.Value{e.value, v})[0].Bool() { |
| 170 | return e |
| 171 | } |
| 172 | } |
| 173 | return nil |
| 174 | } |
| 175 | |
| 176 | subR.Range(func(_, v any) bool { |
| 177 | rv := reflect.ValueOf(v) |
| 178 | e := findEntry(rv) |
| 179 | if e == nil { |
| 180 | entries[&entry{ |
| 181 | value: rv, |
| 182 | found: 1, |
| 183 | }] = struct{}{} |
| 184 | } else { |
| 185 | e.found++ |
| 186 | } |
| 187 | return true |
| 188 | }) |
| 189 | supR.Range(func(_, v any) bool { |
| 190 | rv := reflect.ValueOf(v) |
| 191 | e := findEntry(rv) |
| 192 | if e == nil { |
| 193 | return true |
| 194 | } |
| 195 | if e.found == 1 { |