File: set_intersection.go

package info (click to toggle)
golang-github-apparentlymart-go-versions 1.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 292 kB
  • sloc: makefile: 2
file content (132 lines) | stat: -rw-r--r-- 2,751 bytes parent folder | download
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
126
127
128
129
130
131
132
package versions

import (
	"bytes"
	"fmt"
)

type setIntersection []setI

func (s setIntersection) Has(v Version) bool {
	if len(s) == 0 {
		// Weird to have an intersection with no elements, but we'll
		// allow it and return something sensible.
		return false
	}
	for _, ss := range s {
		if !ss.Has(v) {
			return false
		}
	}
	return true
}

func (s setIntersection) AllRequested() Set {
	// The requested set for an intersection is the union of all of its
	// members requested sets intersection the receiver. Therefore we'll
	// borrow the same logic from setUnion's implementation here but
	// then wrap it up in a setIntersection before we return.

	asUnion := setUnion(s)
	ar := asUnion.AllRequested()
	si := make(setIntersection, len(s)+1)
	si[0] = ar.setI
	copy(si[1:], s)
	return Set{setI: si}
}

func (s setIntersection) GoString() string {
	var buf bytes.Buffer
	fmt.Fprint(&buf, "versions.Intersection(")
	for i, ss := range s {
		if i == 0 {
			fmt.Fprint(&buf, ss.GoString())
		} else {
			fmt.Fprintf(&buf, ", %#v", ss)
		}
	}
	fmt.Fprint(&buf, ")")
	return buf.String()
}

// Intersection creates a new set that contains the versions that all of the
// given sets have in common.
//
// The result is finite if any of the given sets are finite.
func Intersection(sets ...Set) Set {
	if len(sets) == 0 {
		return None
	}

	r := make(setIntersection, 0, len(sets))
	for _, set := range sets {
		if set == All {
			continue
		}
		if set == None {
			return None
		}
		if su, ok := set.setI.(setIntersection); ok {
			r = append(r, su...)
		} else {
			r = append(r, set.setI)
		}
	}
	if len(r) == 1 {
		return Set{setI: r[0]}
	}
	return Set{setI: r}
}

// Intersection returns a new set that contains all of the versions that
// the receiver and the given sets have in common.
//
// The result is a finite set if the receiver or any of the given sets are
// finite.
func (s Set) Intersection(others ...Set) Set {
	r := make(setIntersection, 1, len(others)+1)
	r[0] = s.setI
	for _, ss := range others {
		if ss == All {
			continue
		}
		if ss == None {
			return None
		}
		if su, ok := ss.setI.(setIntersection); ok {
			r = append(r, su...)
		} else {
			r = append(r, ss.setI)
		}
	}
	if len(r) == 1 {
		return Set{setI: r[0]}
	}
	return Set{setI: r}
}

var _ setFinite = setIntersection{}

func (s setIntersection) isFinite() bool {
	// intersection is finite if any of its members are, or if it is empty
	if len(s) == 0 {
		return true
	}
	for _, ss := range s {
		if isFinite(ss) {
			return true
		}
	}
	return false
}

func (s setIntersection) listVersions() List {
	var ret List
	for _, ss := range s {
		if isFinite(ss) {
			ret = append(ret, ss.(setFinite).listVersions()...)
		}
	}
	ret.Filter(Set{setI: s})
	return ret
}