1+ use std:: marker:: PhantomData ;
2+
13use pyo3:: exceptions:: PyValueError ;
24use pyo3:: ffi;
35use pyo3:: prelude:: * ;
@@ -31,45 +33,52 @@ pub fn python_parse<'py>(
3133 cache_mode : StringCacheMode ,
3234 allow_partial : bool ,
3335) -> JsonResult < Bound < ' py , PyAny > > {
34- let mut python_parser = PythonParser {
35- parser : Parser :: new ( json_data) ,
36- tape : Tape :: default ( ) ,
37- recursion_limit : DEFAULT_RECURSION_LIMIT ,
38- allow_inf_nan,
39- allow_partial,
40- } ;
41-
42- let peek = python_parser. parser . peek ( ) ?;
43- let v = match cache_mode {
44- StringCacheMode :: All => python_parser. py_take_value :: < StringCacheAll > ( py, peek) ?,
45- StringCacheMode :: Keys => python_parser. py_take_value :: < StringCacheKeys > ( py, peek) ?,
46- StringCacheMode :: None => python_parser. py_take_value :: < StringNoCache > ( py, peek) ?,
47- } ;
48- if !allow_partial {
49- python_parser. parser . finish ( ) ?;
36+ match cache_mode {
37+ StringCacheMode :: All => PythonParser :: < StringCacheAll > :: parse ( py, json_data, allow_inf_nan, allow_partial) ,
38+ StringCacheMode :: Keys => PythonParser :: < StringCacheKeys > :: parse ( py, json_data, allow_inf_nan, allow_partial) ,
39+ StringCacheMode :: None => PythonParser :: < StringNoCache > :: parse ( py, json_data, allow_inf_nan, allow_partial) ,
5040 }
51- Ok ( v)
5241}
5342
5443/// Map a `JsonError` to a `PyErr` which can be raised as an exception in Python as a `ValueError`.
5544pub fn map_json_error ( json_data : & [ u8 ] , json_error : & JsonError ) -> PyErr {
5645 PyValueError :: new_err ( json_error. description ( json_data) )
5746}
5847
59- struct PythonParser < ' j > {
48+ struct PythonParser < ' j , StringCache > {
49+ _string_cache : PhantomData < StringCache > ,
6050 parser : Parser < ' j > ,
6151 tape : Tape ,
6252 recursion_limit : u8 ,
6353 allow_inf_nan : bool ,
6454 allow_partial : bool ,
6555}
6656
67- impl < ' j > PythonParser < ' j > {
68- fn py_take_value < ' py , StringCache : StringMaybeCache > (
69- & mut self ,
57+ impl < ' j , StringCache : StringMaybeCache > PythonParser < ' j , StringCache > {
58+ fn parse < ' py > (
7059 py : Python < ' py > ,
71- peek : Peek ,
60+ json_data : & [ u8 ] ,
61+ allow_inf_nan : bool ,
62+ allow_partial : bool ,
7263 ) -> JsonResult < Bound < ' py , PyAny > > {
64+ let mut slf = PythonParser {
65+ _string_cache : PhantomData :: < StringCache > ,
66+ parser : Parser :: new ( json_data) ,
67+ tape : Tape :: default ( ) ,
68+ recursion_limit : DEFAULT_RECURSION_LIMIT ,
69+ allow_inf_nan,
70+ allow_partial,
71+ } ;
72+
73+ let peek = slf. parser . peek ( ) ?;
74+ let v = slf. py_take_value ( py, peek) ?;
75+ if !allow_partial {
76+ slf. parser . finish ( ) ?;
77+ }
78+ Ok ( v)
79+ }
80+
81+ fn py_take_value < ' py > ( & mut self , py : Python < ' py > , peek : Peek ) -> JsonResult < Bound < ' py , PyAny > > {
7382 match peek {
7483 Peek :: Null => {
7584 self . parser . consume_null ( ) ?;
@@ -95,7 +104,7 @@ impl<'j> PythonParser<'j> {
95104 } ;
96105
97106 let mut vec: SmallVec < [ Bound < ' _ , PyAny > ; 8 ] > = SmallVec :: with_capacity ( 8 ) ;
98- if let Err ( e) = self . _parse_array :: < StringCache > ( py, peek_first, & mut vec) {
107+ if let Err ( e) = self . _parse_array ( py, peek_first, & mut vec) {
99108 if !self . _allow_partial_err ( & e) {
100109 return Err ( e) ;
101110 }
@@ -105,7 +114,7 @@ impl<'j> PythonParser<'j> {
105114 }
106115 Peek :: Object => {
107116 let dict = PyDict :: new_bound ( py) ;
108- if let Err ( e) = self . _parse_object :: < StringCache > ( py, & dict) {
117+ if let Err ( e) = self . _parse_object ( py, & dict) {
109118 if !self . _allow_partial_err ( & e) {
110119 return Err ( e) ;
111120 }
@@ -132,26 +141,22 @@ impl<'j> PythonParser<'j> {
132141 }
133142 }
134143
135- fn _parse_array < ' py , StringCache : StringMaybeCache > (
144+ fn _parse_array < ' py > (
136145 & mut self ,
137146 py : Python < ' py > ,
138147 peek_first : Peek ,
139148 vec : & mut SmallVec < [ Bound < ' py , PyAny > ; 8 ] > ,
140149 ) -> JsonResult < ( ) > {
141- let v = self . _check_take_value :: < StringCache > ( py, peek_first) ?;
150+ let v = self . _check_take_value ( py, peek_first) ?;
142151 vec. push ( v) ;
143152 while let Some ( peek) = self . parser . array_step ( ) ? {
144- let v = self . _check_take_value :: < StringCache > ( py, peek) ?;
153+ let v = self . _check_take_value ( py, peek) ?;
145154 vec. push ( v) ;
146155 }
147156 Ok ( ( ) )
148157 }
149158
150- fn _parse_object < ' py , StringCache : StringMaybeCache > (
151- & mut self ,
152- py : Python < ' py > ,
153- dict : & Bound < ' py , PyDict > ,
154- ) -> JsonResult < ( ) > {
159+ fn _parse_object < ' py > ( & mut self , py : Python < ' py > , dict : & Bound < ' py , PyDict > ) -> JsonResult < ( ) > {
155160 let set_item = |key : Bound < ' py , PyString > , value : Bound < ' py , PyAny > | {
156161 let r = unsafe { ffi:: PyDict_SetItem ( dict. as_ptr ( ) , key. as_ptr ( ) , value. as_ptr ( ) ) } ;
157162 // AFAIK this shouldn't happen since the key will always be a string which is hashable
@@ -164,12 +169,12 @@ impl<'j> PythonParser<'j> {
164169 if let Some ( first_key) = self . parser . object_first :: < StringDecoder > ( & mut self . tape ) ? {
165170 let first_key = StringCache :: get_key ( py, first_key. as_str ( ) , first_key. ascii_only ( ) ) ;
166171 let peek = self . parser . peek ( ) ?;
167- let first_value = self . _check_take_value :: < StringCache > ( py, peek) ?;
172+ let first_value = self . _check_take_value ( py, peek) ?;
168173 set_item ( first_key, first_value) ;
169174 while let Some ( key) = self . parser . object_step :: < StringDecoder > ( & mut self . tape ) ? {
170175 let key = StringCache :: get_key ( py, key. as_str ( ) , key. ascii_only ( ) ) ;
171176 let peek = self . parser . peek ( ) ?;
172- let value = self . _check_take_value :: < StringCache > ( py, peek) ?;
177+ let value = self . _check_take_value ( py, peek) ?;
173178 set_item ( key, value) ;
174179 }
175180 }
@@ -192,17 +197,13 @@ impl<'j> PythonParser<'j> {
192197 }
193198 }
194199
195- fn _check_take_value < ' py , StringCache : StringMaybeCache > (
196- & mut self ,
197- py : Python < ' py > ,
198- peek : Peek ,
199- ) -> JsonResult < Bound < ' py , PyAny > > {
200+ fn _check_take_value < ' py > ( & mut self , py : Python < ' py > , peek : Peek ) -> JsonResult < Bound < ' py , PyAny > > {
200201 self . recursion_limit = match self . recursion_limit . checked_sub ( 1 ) {
201202 Some ( limit) => limit,
202203 None => return json_err ! ( RecursionLimitExceeded , self . parser. index) ,
203204 } ;
204205
205- let r = self . py_take_value :: < StringCache > ( py, peek) ;
206+ let r = self . py_take_value ( py, peek) ;
206207
207208 self . recursion_limit += 1 ;
208209 r
0 commit comments