@@ -174,8 +174,8 @@ macro_rules! then_some_closure {
174174 } ;
175175}
176176
177- fn length_wrapper ( obj : PyObjectRef , vm : & VirtualMachine ) -> PyResult < usize > {
178- let ret = vm. call_special_method ( obj, identifier ! ( vm, __len__) , ( ) ) ?;
177+ fn length_wrapper ( obj : & PyObject , vm : & VirtualMachine ) -> PyResult < usize > {
178+ let ret = vm. call_special_method ( obj. to_owned ( ) , identifier ! ( vm, __len__) , ( ) ) ?;
179179 let len = ret. payload :: < PyInt > ( ) . ok_or_else ( || {
180180 vm. new_type_error ( format ! (
181181 "'{}' object cannot be interpreted as an integer" ,
@@ -192,26 +192,30 @@ fn length_wrapper(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
192192 Ok ( len as usize )
193193}
194194
195- fn as_mapping_wrapper ( zelf : & PyObject , vm : & VirtualMachine ) -> PyMappingMethods {
195+ const fn new_as_mapping_wrapper (
196+ has_length : bool ,
197+ has_subscript : bool ,
198+ has_ass_subscript : bool ,
199+ ) -> PyMappingMethods {
196200 PyMappingMethods {
197- length : then_some_closure ! (
198- zelf . class ( ) . has_attr ( identifier! ( vm , __len__ ) ) ,
199- |mapping , vm| { length_wrapper ( mapping . obj . to_owned ( ) , vm ) }
200- ) ,
201- subscript : then_some_closure ! (
202- zelf . class ( ) . has_attr ( identifier! ( vm , __getitem__ ) ) ,
203- |mapping, needle, vm| {
201+ length : if has_length {
202+ Some ( |mapping , vm| length_wrapper ( & mapping . obj , vm ) )
203+ } else {
204+ None
205+ } ,
206+ subscript : if has_subscript {
207+ Some ( |mapping, needle, vm| {
204208 vm. call_special_method (
205209 mapping. obj . to_owned ( ) ,
206210 identifier ! ( vm, __getitem__) ,
207211 ( needle. to_owned ( ) , ) ,
208212 )
209- }
210- ) ,
211- ass_subscript : then_some_closure ! (
212- zelf . class ( ) . has_attr ( identifier! ( vm , __setitem__ ) )
213- | zelf . class ( ) . has_attr ( identifier! ( vm , __delitem__ ) ) ,
214- |mapping, needle, value, vm| match value {
213+ } )
214+ } else {
215+ None
216+ } ,
217+ ass_subscript : if has_ass_subscript {
218+ Some ( |mapping, needle, value, vm| match value {
215219 Some ( value) => vm
216220 . call_special_method (
217221 mapping. obj . to_owned ( ) ,
@@ -223,12 +227,44 @@ fn as_mapping_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyMappingMethods
223227 . call_special_method (
224228 mapping. obj . to_owned ( ) ,
225229 identifier ! ( vm, __delitem__) ,
226- ( needle. to_owned( ) , )
230+ ( needle. to_owned ( ) , ) ,
227231 )
228232 . map ( |_| Ok ( ( ) ) ) ?,
229- }
230- ) ,
233+ } )
234+ } else {
235+ None
236+ } ,
237+ }
238+ }
239+
240+ fn as_mapping_wrapper ( zelf : & PyObject , vm : & VirtualMachine ) -> PyMappingMethods {
241+ static MAPPING_METHODS : & [ PyMappingMethods ] = & [
242+ new_as_mapping_wrapper ( false , false , false ) ,
243+ new_as_mapping_wrapper ( true , false , false ) ,
244+ new_as_mapping_wrapper ( false , true , false ) ,
245+ new_as_mapping_wrapper ( true , true , false ) ,
246+ new_as_mapping_wrapper ( false , false , true ) ,
247+ new_as_mapping_wrapper ( true , false , true ) ,
248+ new_as_mapping_wrapper ( false , true , true ) ,
249+ new_as_mapping_wrapper ( true , true , true ) ,
250+ ] ;
251+ const fn bool_int ( v : bool ) -> usize {
252+ if v {
253+ 1
254+ } else {
255+ 0
256+ }
231257 }
258+ let ( has_length, has_subscript, has_ass_subscript) = (
259+ zelf. class ( ) . has_attr ( identifier ! ( vm, __len__) ) ,
260+ zelf. class ( ) . has_attr ( identifier ! ( vm, __getitem__) ) ,
261+ zelf. class ( ) . has_attr ( identifier ! ( vm, __setitem__) )
262+ | zelf. class ( ) . has_attr ( identifier ! ( vm, __delitem__) ) ,
263+ ) ;
264+ let key = ( bool_int ( has_length) << 0 )
265+ | ( bool_int ( has_subscript) << 1 )
266+ | ( bool_int ( has_ass_subscript) << 2 ) ;
267+ MAPPING_METHODS [ key] . clone ( )
232268}
233269
234270fn as_sequence_wrapper ( zelf : & PyObject , vm : & VirtualMachine ) -> Cow < ' static , PySequenceMethods > {
@@ -239,7 +275,7 @@ fn as_sequence_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> Cow<'static, PyS
239275 Cow :: Owned ( PySequenceMethods {
240276 length : then_some_closure ! (
241277 zelf. class( ) . has_attr( identifier!( vm, __len__) ) ,
242- |seq, vm| { length_wrapper( seq. obj. to_owned ( ) , vm) }
278+ |seq, vm| { length_wrapper( & seq. obj, vm) }
243279 ) ,
244280 item : Some ( |seq, i, vm| {
245281 vm. call_special_method (
0 commit comments