11package comver
22
3- type Or []CeilingFloorConstrainter
3+ import (
4+ "slices"
5+ )
6+
7+ // Or represents a logical OR operation between multiple [CeilingFloorConstrainter] instances.
8+ // The zero value of Or is a constraint could never be satisfied.
9+ type Or []CeilingFloorConstrainter //nolint:godox // TODO: Use Constrainter so that we can nest Or.
410
511func (o Or ) Check (v Version ) bool {
6- return true // TODO: Implement!
12+ for i := range o {
13+ if o [i ].Check (v ) {
14+ return true
15+ }
16+ }
17+ return false
718}
819
9- //func CompactOr(cs Or) Constrainter {
10- // if len(cs) == 0 {
11- // return NewWildcard()
12- // }
13- // if len(cs) == 1 {
14- // return cs[0]
15- // }
16- //
17- // cs = slices.Clone(cs)
18- //
19- // // if there cs a wildcard, return only the wildcard
20- // w := slices.ContainsFunc(cs, func(c CeilingFloorConstrainter) bool {
21- // return c.Floor().version == nil && c.Ceiling().version == nil
22- // })
23- // if w {
24- // return NewWildcard()
25- // }
26- //
27- // head, headOk := minBoundedFloor(cs...)
28- // cs = slices.DeleteFunc(cs, func(c CeilingFloorConstrainter) bool {
29- // return c.Floor().version == nil
30- // })
31- // if headOk {
32- // cs = append(cs, head)
33- // }
34- //
35- // tail, tailOk := maxBoundedCelling(cs)
36- // cs = slices.DeleteFunc(cs, func(c CeilingFloorConstrainter) bool {
37- // return c.Ceiling().version == nil
38- // })
39- // if tailOk {
40- // cs = append(cs, tail)
41- // }
42- //
43- // // TODO: Check whether interval{head, tail} are wildcard.
44- // // If yes, early return wildcard
45- //
46- // // important!
47- // slices.SortFunc(cs, compareSimpleConstrainters)
48- //
49- // // remove duplicates
50- // cs = slices.CompactFunc(cs, func(a, b CeilingFloorConstrainter) bool {
51- // return compareSimpleConstrainters(a, b) == 0
52- // })
53- //
54- // vals := make(Or, 0, len(cs))
55- // pendingI := cs[0]
56- // for index := range cs {
57- // i, ok := compactTwoSCs(pendingI, cs[index])
58- // if ok {
59- // pendingI = i
60- // } else {
61- // vals = append(vals, pendingI)
62- // pendingI = cs[index]
63- // }
64- //
65- // if index == len(cs)-1 {
66- // vals = append(vals, pendingI)
67- // }
68- // }
69- //
70- // return slices.Clip(vals)
71- //}
72-
73- func compactTwoSCs (a , b CeilingFloorConstrainter ) (CeilingFloorConstrainter , bool ) {
74- cmp := compareSimpleConstrainters (a , b )
75- if cmp > 0 {
76- a , b = b , a
20+ func (o Or ) String () string { // TODO: Test me.
21+ s := ""
22+ for i := range o {
23+ if i > 0 {
24+ s += " || "
25+ }
26+ s += o [i ].String ()
7727 }
28+ return s
29+ }
7830
31+ // Compact returns a new [Constrainter] that is logically equivalent to the input o.
32+ // The returned [Constrainter] may or may be not be an [Or] instance.
33+ // When it is, Compact tries to return the shortest [Or] possible.
34+ func Compact (o Or ) Constrainter { // TODO: Test me.
35+ if len (o ) == 0 {
36+ return o
37+ }
38+ if len (o ) == 1 {
39+ return o [0 ]
40+ }
41+
42+ o = slices .Clone (o )
43+
44+ // wildcard trumps everything else.
45+ if slices .ContainsFunc (o , wildcard ) {
46+ return NewWildcard ()
47+ }
48+
49+ ceiling , ceilingOk := maxFloorlessCeiling (o ... )
50+ floor , floorOk := minCeilinglessFloor (o ... )
51+
52+ if ceilingOk && floorOk {
53+ if formWildcard (ceiling .Ceiling (), floor .Floor ()) {
54+ return NewWildcard ()
55+ }
56+ }
57+
58+ o = slices .DeleteFunc (o , func (c CeilingFloorConstrainter ) bool {
59+ return c .Ceiling ().wildcard () || c .Floor ().wildcard ()
60+ })
61+
62+ // important to sort before compacting
63+ slices .SortFunc (o , compareCeilingFloorConstrainters )
64+ // remove duplicates
65+ o = slices .CompactFunc (o , func (a , b CeilingFloorConstrainter ) bool {
66+ return compareCeilingFloorConstrainters (a , b ) == 0
67+ })
68+
69+ vals := make (Or , 0 , len (o )+ 2 )
70+ pendingI := o [0 ]
71+ for index := range o {
72+ i , ok := compactTwo (pendingI , o [index ])
73+ if ok {
74+ pendingI = i
75+ } else {
76+ vals = append (vals , pendingI )
77+ pendingI = o [index ]
78+ }
79+
80+ if index == len (o )- 1 {
81+ vals = append (vals , pendingI )
82+ }
83+ }
84+
85+ var head Or
86+ if floorOk {
87+ head = append (head , floor )
88+ }
89+ var tail Or
90+ if ceilingOk {
91+ tail = append (tail , ceiling )
92+ }
93+
94+ r := slices .Concat (head , vals , tail )
95+ return slices .Clip (r )
96+ }
97+
98+ // TODO: Test me.
99+ func compactTwo (a , b CeilingFloorConstrainter ) (CeilingFloorConstrainter , bool ) {
100+ cmp := compareCeilingFloorConstrainters (a , b )
79101 if cmp == 0 {
80102 return a , true
81103 }
82104
105+ if cmp > 0 {
106+ a , b = b , a
107+ }
108+
83109 if ! overlap (a , b ) && ! seamless (a , b ) {
84110 return a , false
85111 }
@@ -91,10 +117,51 @@ func compactTwoSCs(a, b CeilingFloorConstrainter) (CeilingFloorConstrainter, boo
91117 return interval {a .Floor (), b .Ceiling ()}, true
92118}
93119
94- func compareSimpleConstrainters (a , b CeilingFloorConstrainter ) int {
120+ // TODO: Test me.
121+ func compareCeilingFloorConstrainters (a , b CeilingFloorConstrainter ) int {
95122 cmp := a .Floor ().compare (b .Floor ())
96123 if cmp != 0 {
97124 return cmp
98125 }
99126 return a .Ceiling ().compare (b .Ceiling ())
100127}
128+
129+ // TODO: Test me.
130+ func formWildcard (e , f Endless ) bool {
131+ if e .wildcard () {
132+ return true
133+ }
134+
135+ if f .wildcard () {
136+ return true
137+ }
138+
139+ if e .op .ceilingBounded () && f .op .ceilingBounded () {
140+ return false
141+ }
142+
143+ if e .op .floorBounded () && f .op .floorBounded () {
144+ return false
145+ }
146+
147+ cmp := e .compare (f )
148+
149+ if cmp == 0 {
150+ return false
151+ }
152+
153+ if cmp > 0 {
154+ e , f = f , e
155+ }
156+
157+ vCmp := e .version .Compare (* f .version )
158+ if vCmp == 0 {
159+ return e .inclusive () || f .inclusive ()
160+ }
161+
162+ if e .op .ceilingBounded () || f .op .floorBounded () {
163+ return false
164+ }
165+
166+ return false
167+ }
0 commit comments