1
1
use std:: borrow:: Cow ;
2
2
use std:: slice:: Iter as SliceIter ;
3
3
4
- use pyo3:: intern;
5
4
use pyo3:: prelude:: * ;
6
5
use pyo3:: types:: iter:: PyDictIterator ;
7
6
use pyo3:: types:: { PyBytes , PyDict , PyFrozenSet , PyIterator , PyList , PyMapping , PySet , PyString , PyTuple } ;
7
+ use pyo3:: { ffi, intern, AsPyPointer , PyNativeType } ;
8
8
9
9
#[ cfg( not( PyPy ) ) ]
10
10
use pyo3:: types:: PyFunction ;
11
11
#[ cfg( not( PyPy ) ) ]
12
12
use pyo3:: PyTypeInfo ;
13
13
14
14
use crate :: errors:: { py_err_string, ErrorType , InputValue , ValError , ValLineError , ValResult } ;
15
+ use crate :: input:: py_error_on_minusone;
15
16
use crate :: recursion_guard:: RecursionGuard ;
16
17
use crate :: validators:: { CombinedValidator , Extra , Validator } ;
17
18
@@ -131,9 +132,41 @@ fn validate_iter_to_vec<'a, 's>(
131
132
}
132
133
}
133
134
135
+ pub trait BuildSet {
136
+ fn build_add ( & self , item : PyObject ) -> PyResult < ( ) > ;
137
+
138
+ fn build_len ( & self ) -> usize ;
139
+ }
140
+
141
+ impl BuildSet for & PySet {
142
+ fn build_add ( & self , item : PyObject ) -> PyResult < ( ) > {
143
+ self . add ( item)
144
+ }
145
+
146
+ fn build_len ( & self ) -> usize {
147
+ self . len ( )
148
+ }
149
+ }
150
+
151
+ impl BuildSet for & PyFrozenSet {
152
+ fn build_add ( & self , item : PyObject ) -> PyResult < ( ) > {
153
+ unsafe {
154
+ py_error_on_minusone (
155
+ self . py ( ) ,
156
+ ffi:: PySet_Add ( self . as_ptr ( ) , item. to_object ( self . py ( ) ) . as_ptr ( ) ) ,
157
+ )
158
+ }
159
+ }
160
+
161
+ fn build_len ( & self ) -> usize {
162
+ self . len ( )
163
+ }
164
+ }
165
+
134
166
#[ allow( clippy:: too_many_arguments) ]
135
167
fn validate_iter_to_set < ' a , ' s > (
136
168
py : Python < ' a > ,
169
+ set : impl BuildSet ,
137
170
iter : impl Iterator < Item = PyResult < & ' a ( impl Input < ' a > + ' a ) > > ,
138
171
input : & ' a ( impl Input < ' a > + ' a ) ,
139
172
field_type : & ' static str ,
@@ -142,16 +175,15 @@ fn validate_iter_to_set<'a, 's>(
142
175
extra : & Extra ,
143
176
definitions : & ' a [ CombinedValidator ] ,
144
177
recursion_guard : & ' s mut RecursionGuard ,
145
- ) -> ValResult < ' a , & ' a PySet > {
146
- let set = PySet :: empty ( py) ?;
178
+ ) -> ValResult < ' a , ( ) > {
147
179
let mut errors: Vec < ValLineError > = Vec :: new ( ) ;
148
180
for ( index, item_result) in iter. enumerate ( ) {
149
181
let item = item_result. map_err ( |e| any_next_error ! ( py, e, input, index) ) ?;
150
182
match validator. validate ( py, item, extra, definitions, recursion_guard) {
151
183
Ok ( item) => {
152
- set. add ( item) ?;
184
+ set. build_add ( item) ?;
153
185
if let Some ( max_length) = max_length {
154
- let actual_length = set. len ( ) ;
186
+ let actual_length = set. build_len ( ) ;
155
187
if actual_length > max_length {
156
188
return Err ( ValError :: new (
157
189
ErrorType :: TooLong {
@@ -173,7 +205,7 @@ fn validate_iter_to_set<'a, 's>(
173
205
}
174
206
175
207
if errors. is_empty ( ) {
176
- Ok ( set )
208
+ Ok ( ( ) )
177
209
} else {
178
210
Err ( ValError :: LineErrors ( errors) )
179
211
}
@@ -252,18 +284,20 @@ impl<'a> GenericCollection<'a> {
252
284
pub fn validate_to_set < ' s > (
253
285
& ' s self ,
254
286
py : Python < ' a > ,
287
+ set : impl BuildSet ,
255
288
input : & ' a impl Input < ' a > ,
256
289
max_length : Option < usize > ,
257
290
field_type : & ' static str ,
258
291
validator : & ' s CombinedValidator ,
259
292
extra : & Extra ,
260
293
definitions : & ' a [ CombinedValidator ] ,
261
294
recursion_guard : & ' s mut RecursionGuard ,
262
- ) -> ValResult < ' a , & ' a PySet > {
295
+ ) -> ValResult < ' a , ( ) > {
263
296
macro_rules! validate_set {
264
297
( $iter: expr) => {
265
298
validate_iter_to_set(
266
299
py,
300
+ set,
267
301
$iter,
268
302
input,
269
303
field_type,
0 commit comments