@@ -21,6 +21,7 @@ use std::mem;
21
21
22
22
use starlark_derive:: starlark_module;
23
23
use starlark_map:: small_set:: SmallSet ;
24
+ use starlark_map:: Hashed ;
24
25
use starlark_syntax:: value_error;
25
26
26
27
use crate as starlark;
@@ -34,6 +35,43 @@ use crate::values::Heap;
34
35
use crate :: values:: Value ;
35
36
use crate :: values:: ValueOfUnchecked ;
36
37
38
+ enum SetFromValue < ' v > {
39
+ Set ( SmallSet < Value < ' v > > ) ,
40
+ }
41
+
42
+ impl < ' v > SetFromValue < ' v > {
43
+ fn from_value (
44
+ value : ValueOfUnchecked < ' v , StarlarkIter < Value < ' v > > > ,
45
+ heap : & ' v Heap ,
46
+ ) -> crate :: Result < Self > {
47
+ let mut set = SmallSet :: default ( ) ;
48
+ for elem in value. get ( ) . iterate ( heap) ? {
49
+ set. insert_hashed ( elem. get_hashed ( ) ?) ;
50
+ }
51
+ Ok ( SetFromValue :: Set ( set) )
52
+ }
53
+
54
+ fn get ( & self ) -> & SmallSet < Value < ' v > > {
55
+ match self {
56
+ SetFromValue :: Set ( set) => set,
57
+ }
58
+ }
59
+
60
+ fn into_set ( self ) -> SmallSet < Value < ' v > > {
61
+ match self {
62
+ SetFromValue :: Set ( set) => set,
63
+ }
64
+ }
65
+
66
+ fn is_empty ( & self ) -> bool {
67
+ self . get ( ) . is_empty ( )
68
+ }
69
+
70
+ fn contains_hashed ( & self , value : Hashed < Value < ' v > > ) -> bool {
71
+ self . get ( ) . contains_hashed ( value. as_ref ( ) )
72
+ }
73
+ }
74
+
37
75
#[ starlark_module]
38
76
pub ( crate ) fn set_methods ( builder : & mut MethodsBuilder ) {
39
77
fn clear ( this : Value ) -> anyhow:: Result < NoneType > {
@@ -81,18 +119,14 @@ pub(crate) fn set_methods(builder: &mut MethodsBuilder) {
81
119
heap : & ' v Heap ,
82
120
) -> starlark:: Result < SetData < ' v > > {
83
121
//TODO(romanp) check if other is set
84
- let other_it = other. get ( ) . iterate ( heap) ?;
85
- let mut other_set = SmallSet :: default ( ) ;
86
- for elem in other_it {
87
- other_set. insert_hashed ( elem. get_hashed ( ) ?) ;
88
- }
122
+ let other_set = SetFromValue :: from_value ( other, heap) ?;
89
123
let mut data = SetData :: default ( ) ;
90
124
if other_set. is_empty ( ) {
91
125
return Ok ( data) ;
92
126
}
93
127
94
128
for hashed in this. aref . content . iter_hashed ( ) {
95
- if other_set. contains_hashed ( hashed) {
129
+ if other_set. contains_hashed ( hashed. copied ( ) ) {
96
130
data. content . insert_hashed_unique_unchecked ( hashed. copied ( ) ) ;
97
131
}
98
132
}
@@ -113,11 +147,7 @@ pub(crate) fn set_methods(builder: &mut MethodsBuilder) {
113
147
heap : & ' v Heap ,
114
148
) -> starlark:: Result < SetData < ' v > > {
115
149
//TODO(romanp) check if other is set
116
- let other_it = other. get ( ) . iterate ( heap) ?;
117
- let mut other_set: SmallSet < Value < ' v > > = SmallSet :: default ( ) ;
118
- for elem in other_it {
119
- other_set. insert_hashed ( elem. get_hashed ( ) ?) ;
120
- }
150
+ let other_set = SetFromValue :: from_value ( other, heap) ?;
121
151
122
152
if other_set. is_empty ( ) {
123
153
return Ok ( SetData {
@@ -127,17 +157,19 @@ pub(crate) fn set_methods(builder: &mut MethodsBuilder) {
127
157
128
158
//TODO(romanp) add symmetric_difference to small set and use it here and in xor
129
159
if this. aref . content . is_empty ( ) {
130
- return Ok ( SetData { content : other_set } ) ;
160
+ return Ok ( SetData {
161
+ content : other_set. into_set ( ) ,
162
+ } ) ;
131
163
}
132
164
133
165
let mut data = SetData :: default ( ) ;
134
166
for elem in this. aref . content . iter_hashed ( ) {
135
- if !other_set. contains_hashed ( elem) {
167
+ if !other_set. contains_hashed ( elem. copied ( ) ) {
136
168
data. add_hashed ( elem. copied ( ) ) ;
137
169
}
138
170
}
139
171
140
- for elem in other_set {
172
+ for elem in other_set. get ( ) {
141
173
let hashed = elem. get_hashed ( ) ?;
142
174
if !this. aref . content . contains_hashed ( hashed. as_ref ( ) ) {
143
175
data. add_hashed ( hashed) ;
@@ -276,16 +308,13 @@ pub(crate) fn set_methods(builder: &mut MethodsBuilder) {
276
308
heap : & ' v Heap ,
277
309
) -> starlark:: Result < SetData < ' v > > {
278
310
//TODO(romanp) check if other is set
279
- let other_it = other. get ( ) . iterate ( heap) ?;
280
311
281
312
if this. aref . content . is_empty ( ) {
313
+ other. get ( ) . iterate ( heap) ?;
282
314
return Ok ( SetData :: default ( ) ) ;
283
315
}
284
316
285
- let mut other_set: SmallSet < Value < ' v > > = SmallSet :: default ( ) ;
286
- for elem in other_it {
287
- other_set. insert_hashed ( elem. get_hashed ( ) ?) ;
288
- }
317
+ let other_set = SetFromValue :: from_value ( other, heap) ?;
289
318
290
319
if other_set. is_empty ( ) {
291
320
return Ok ( SetData {
@@ -295,7 +324,7 @@ pub(crate) fn set_methods(builder: &mut MethodsBuilder) {
295
324
296
325
let mut data = SetData :: default ( ) ;
297
326
for elem in this. aref . content . iter_hashed ( ) {
298
- if !other_set. contains_hashed ( elem) {
327
+ if !other_set. contains_hashed ( elem. copied ( ) ) {
299
328
data. add_hashed ( elem. copied ( ) ) ;
300
329
}
301
330
}
@@ -339,20 +368,17 @@ pub(crate) fn set_methods(builder: &mut MethodsBuilder) {
339
368
#[ starlark( require=pos) ] other : ValueOfUnchecked < ' v , StarlarkIter < Value < ' v > > > ,
340
369
heap : & ' v Heap ,
341
370
) -> starlark:: Result < bool > {
342
- let other = other. get ( ) . iterate ( heap) ?;
343
371
if this. aref . content . is_empty ( ) {
372
+ other. get ( ) . iterate ( heap) ?;
344
373
return Ok ( true ) ;
345
374
}
346
375
//TODO(romanp): check if other is already a set
347
- let mut rhs: SmallSet < Value < ' v > > = SmallSet :: default ( ) ;
348
- for elem in other {
349
- rhs. insert_hashed ( elem. get_hashed ( ) ?) ;
350
- }
376
+ let rhs = SetFromValue :: from_value ( other, heap) ?;
351
377
if rhs. is_empty ( ) {
352
378
return Ok ( false ) ;
353
379
}
354
380
for elem in this. aref . content . iter_hashed ( ) {
355
- if !rhs. contains_hashed ( elem) {
381
+ if !rhs. contains_hashed ( elem. copied ( ) ) {
356
382
return Ok ( false ) ;
357
383
}
358
384
}
0 commit comments