@@ -5,13 +5,12 @@ mod machinery;
5
5
mod _json {
6
6
use super :: machinery;
7
7
use crate :: vm:: {
8
- builtins:: PyBaseExceptionRef ,
9
- builtins:: { PyStrRef , PyTypeRef } ,
8
+ builtins:: { PyBaseExceptionRef , PyStrRef , PyTypeRef } ,
10
9
function:: { FuncArgs , OptionalArg } ,
11
- iterator ,
10
+ protocol :: PyIterReturn ,
12
11
slots:: { Callable , SlotConstructor } ,
13
- IdProtocol , IntoPyObject , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
14
- VirtualMachine ,
12
+ IdProtocol , IntoPyObject , IntoPyResult , PyObjectRef , PyRef , PyResult , PyValue ,
13
+ TryFromObject , VirtualMachine ,
15
14
} ;
16
15
use num_bigint:: BigInt ;
17
16
use std:: str:: FromStr ;
@@ -74,42 +73,48 @@ mod _json {
74
73
idx : usize ,
75
74
scan_once : PyObjectRef ,
76
75
vm : & VirtualMachine ,
77
- ) -> PyResult {
78
- let c = s
79
- . chars ( )
80
- . next ( )
81
- . ok_or_else ( || iterator :: stop_iter_with_value ( vm . ctx . new_int ( idx ) , vm ) ) ? ;
76
+ ) -> PyResult < PyIterReturn > {
77
+ let c = match s . chars ( ) . next ( ) {
78
+ Some ( c ) => c ,
79
+ None => return Ok ( PyIterReturn :: StopIteration ( Some ( vm . ctx . new_int ( idx ) ) ) ) ,
80
+ } ;
82
81
let next_idx = idx + c. len_utf8 ( ) ;
83
82
match c {
84
83
'"' => {
85
84
return scanstring ( pystr, next_idx, OptionalArg :: Present ( self . strict ) , vm)
86
- . map ( |x| x. into_pyobject ( vm) )
85
+ . map ( |x| PyIterReturn :: Return ( x. into_pyobject ( vm) ) )
87
86
}
88
87
'{' => {
89
88
// TODO: parse the object in rust
90
89
let parse_obj = vm. get_attribute ( self . ctx . clone ( ) , "parse_object" ) ?;
91
- return vm. invoke (
92
- & parse_obj,
93
- (
94
- vm. ctx
95
- . new_tuple ( vec ! [ pystr. into_object( ) , vm. ctx. new_int( next_idx) ] ) ,
96
- self . strict ,
97
- scan_once,
98
- self . object_hook . clone ( ) ,
99
- self . object_pairs_hook . clone ( ) ,
90
+ return PyIterReturn :: from_pyresult (
91
+ vm. invoke (
92
+ & parse_obj,
93
+ (
94
+ vm. ctx
95
+ . new_tuple ( vec ! [ pystr. into_object( ) , vm. ctx. new_int( next_idx) ] ) ,
96
+ self . strict ,
97
+ scan_once,
98
+ self . object_hook . clone ( ) ,
99
+ self . object_pairs_hook . clone ( ) ,
100
+ ) ,
100
101
) ,
102
+ vm,
101
103
) ;
102
104
}
103
105
'[' => {
104
106
// TODO: parse the array in rust
105
107
let parse_array = vm. get_attribute ( self . ctx . clone ( ) , "parse_array" ) ?;
106
- return vm. invoke (
107
- & parse_array,
108
- vec ! [
109
- vm. ctx
110
- . new_tuple( vec![ pystr. into_object( ) , vm. ctx. new_int( next_idx) ] ) ,
111
- scan_once,
112
- ] ,
108
+ return PyIterReturn :: from_pyresult (
109
+ vm. invoke (
110
+ & parse_array,
111
+ vec ! [
112
+ vm. ctx
113
+ . new_tuple( vec![ pystr. into_object( ) , vm. ctx. new_int( next_idx) ] ) ,
114
+ scan_once,
115
+ ] ,
116
+ ) ,
117
+ vm,
113
118
) ;
114
119
}
115
120
_ => { }
@@ -118,7 +123,9 @@ mod _json {
118
123
macro_rules! parse_const {
119
124
( $s: literal, $val: expr) => {
120
125
if s. starts_with( $s) {
121
- return Ok ( vm. ctx. new_tuple( vec![ $val, vm. ctx. new_int( idx + $s. len( ) ) ] ) ) ;
126
+ return Ok ( PyIterReturn :: Return (
127
+ vm. ctx. new_tuple( vec![ $val, vm. ctx. new_int( idx + $s. len( ) ) ] ) ,
128
+ ) ) ;
122
129
}
123
130
} ;
124
131
}
@@ -128,16 +135,18 @@ mod _json {
128
135
parse_const ! ( "false" , vm. ctx. new_bool( false ) ) ;
129
136
130
137
if let Some ( ( res, len) ) = self . parse_number ( s, vm) {
131
- return Ok ( vm. ctx . new_tuple ( vec ! [ res?, vm. ctx. new_int( idx + len) ] ) ) ;
138
+ return Ok ( PyIterReturn :: Return (
139
+ vm. ctx . new_tuple ( vec ! [ res?, vm. ctx. new_int( idx + len) ] ) ,
140
+ ) ) ;
132
141
}
133
142
134
143
macro_rules! parse_constant {
135
144
( $s: literal) => {
136
145
if s. starts_with( $s) {
137
- return Ok ( vm. ctx. new_tuple( vec![
146
+ return Ok ( PyIterReturn :: Return ( vm. ctx. new_tuple( vec![
138
147
vm. invoke( & self . parse_constant, ( $s. to_owned( ) , ) ) ?,
139
148
vm. ctx. new_int( idx + $s. len( ) ) ,
140
- ] ) ) ;
149
+ ] ) ) ) ;
141
150
}
142
151
} ;
143
152
}
@@ -146,7 +155,7 @@ mod _json {
146
155
parse_constant ! ( "Infinity" ) ;
147
156
parse_constant ! ( "-Infinity" ) ;
148
157
149
- Err ( iterator :: stop_iter_with_value ( vm. ctx . new_int ( idx) , vm ) )
158
+ Ok ( PyIterReturn :: StopIteration ( Some ( vm. ctx . new_int ( idx) ) ) )
150
159
}
151
160
152
161
fn parse_number ( & self , s : & str , vm : & VirtualMachine ) -> Option < ( PyResult , usize ) > {
@@ -185,16 +194,19 @@ mod _json {
185
194
Some ( ( ret, buf. len ( ) ) )
186
195
}
187
196
188
- fn call ( zelf : & PyRef < Self > , pystr : PyStrRef , idx : isize , vm : & VirtualMachine ) -> PyResult {
197
+ fn call (
198
+ zelf : & PyRef < Self > ,
199
+ pystr : PyStrRef ,
200
+ idx : isize ,
201
+ vm : & VirtualMachine ,
202
+ ) -> PyResult < PyIterReturn > {
189
203
if idx < 0 {
190
204
return Err ( vm. new_value_error ( "idx cannot be negative" . to_owned ( ) ) ) ;
191
205
}
192
206
let idx = idx as usize ;
193
207
let mut chars = pystr. as_str ( ) . chars ( ) ;
194
- if idx > 0 {
195
- chars
196
- . nth ( idx - 1 )
197
- . ok_or_else ( || iterator:: stop_iter_with_value ( vm. ctx . new_int ( idx) , vm) ) ?;
208
+ if idx > 0 && chars. nth ( idx - 1 ) . is_none ( ) {
209
+ return Ok ( PyIterReturn :: StopIteration ( Some ( vm. ctx . new_int ( idx) ) ) ) ;
198
210
}
199
211
zelf. parse (
200
212
chars. as_str ( ) ,
@@ -209,7 +221,7 @@ mod _json {
209
221
impl Callable for JsonScanner {
210
222
fn call ( zelf : & PyRef < Self > , args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
211
223
let ( pystr, idx) = args. bind :: < ( PyStrRef , isize ) > ( vm) ?;
212
- JsonScanner :: call ( zelf, pystr, idx, vm)
224
+ JsonScanner :: call ( zelf, pystr, idx, vm) . into_pyresult ( vm )
213
225
}
214
226
}
215
227
0 commit comments