@@ -7,13 +7,24 @@ use crate::errors::{JsonError, LinePosition};
77#[ derive( Debug ,  Clone ) ]  
88pub  struct  JsonParseError  { 
99    json_error :  JsonError , 
10+     path :  Vec < PathItem > , 
1011    position :  LinePosition , 
1112} 
1213
1314impl  JsonParseError  { 
14-     pub  fn  new_err ( py :  Python ,  json_error :  JsonError ,  json_data :  & [ u8 ] )  -> PyErr  { 
15-         let  position = json_error. get_position ( json_data) ; 
16-         let  slf = Self  {  json_error,  position } ; 
15+     pub ( crate )  fn  new_err ( py :  Python ,  py_json_error :  PythonJsonError ,  json_data :  & [ u8 ] )  -> PyErr  { 
16+         let  position = py_json_error. error . get_position ( json_data) ; 
17+         let  slf = Self  { 
18+             json_error :  py_json_error. error , 
19+             path :  match  py_json_error. path  { 
20+                 Some ( mut  v)  => { 
21+                     v. reverse ( ) ; 
22+                     v
23+                 } 
24+                 None  => vec ! [ ] , 
25+             } , 
26+             position, 
27+         } ; 
1728        match  Py :: new ( py,  slf)  { 
1829            Ok ( err)  => PyErr :: from_value_bound ( err. into_bound ( py) . into_any ( ) ) , 
1930            Err ( err)  => err, 
@@ -31,6 +42,10 @@ impl JsonParseError {
3142        self . json_error . error_type . to_string ( ) 
3243    } 
3344
45+     fn  path ( & self ,  py :  Python )  -> PyObject  { 
46+         self . path . to_object ( py) 
47+     } 
48+ 
3449    fn  index ( & self )  -> usize  { 
3550        self . json_error . index 
3651    } 
@@ -51,3 +66,136 @@ impl JsonParseError {
5166        format ! ( "JsonParseError({:?})" ,  self . __str__( ) ) 
5267    } 
5368} 
69+ 
70+ pub ( crate )  trait  MaybeBuildArrayPath :  MaybeBuildPath  { 
71+     fn  incr_index ( & mut  self ) ; 
72+     fn  set_index_path ( & self ,  err :  PythonJsonError )  -> PythonJsonError ; 
73+ } 
74+ 
75+ pub ( crate )  trait  MaybeBuildObjectPath :  MaybeBuildPath  { 
76+     fn  set_key ( & mut  self ,  key :  & str ) ; 
77+ 
78+     fn  set_key_path ( & self ,  err :  PythonJsonError )  -> PythonJsonError ; 
79+ } 
80+ 
81+ pub ( crate )  trait  MaybeBuildPath  { 
82+     fn  new_array ( )  -> impl  MaybeBuildArrayPath ; 
83+     fn  new_object ( )  -> impl  MaybeBuildObjectPath ; 
84+ } 
85+ 
86+ pub ( crate )  struct  NoopBuildPath ; 
87+ 
88+ impl  MaybeBuildPath  for  NoopBuildPath  { 
89+     fn  new_array ( )  -> NoopBuildPath  { 
90+         NoopBuildPath 
91+     } 
92+ 
93+     fn  new_object ( )  -> NoopBuildPath  { 
94+         NoopBuildPath 
95+     } 
96+ } 
97+ 
98+ impl  MaybeBuildArrayPath  for  NoopBuildPath  { 
99+     fn  incr_index ( & mut  self )  { } 
100+ 
101+     fn  set_index_path ( & self ,  err :  PythonJsonError )  -> PythonJsonError  { 
102+         err
103+     } 
104+ } 
105+ 
106+ impl  MaybeBuildObjectPath  for  NoopBuildPath  { 
107+     fn  set_key ( & mut  self ,  _:  & str )  { } 
108+ 
109+     fn  set_key_path ( & self ,  err :  PythonJsonError )  -> PythonJsonError  { 
110+         err
111+     } 
112+ } 
113+ 
114+ #[ derive( Default ) ]  
115+ pub ( crate )  struct  ActiveBuildPath  { 
116+     index :  usize , 
117+ } 
118+ 
119+ impl  MaybeBuildPath  for  ActiveBuildPath  { 
120+     fn  new_array ( )  -> ActiveBuildPath  { 
121+         ActiveBuildPath :: default ( ) 
122+     } 
123+ 
124+     fn  new_object ( )  -> ActiveObjectBuildPath  { 
125+         ActiveObjectBuildPath :: default ( ) 
126+     } 
127+ } 
128+ 
129+ impl  MaybeBuildArrayPath  for  ActiveBuildPath  { 
130+     fn  incr_index ( & mut  self )  { 
131+         self . index  += 1 ; 
132+     } 
133+ 
134+     fn  set_index_path ( & self ,  mut  err :  PythonJsonError )  -> PythonJsonError  { 
135+         err. add ( PathItem :: Index ( self . index ) ) ; 
136+         err
137+     } 
138+ } 
139+ 
140+ #[ derive( Default ) ]  
141+ pub ( crate )  struct  ActiveObjectBuildPath  { 
142+     key :  String , 
143+ } 
144+ 
145+ impl  MaybeBuildPath  for  ActiveObjectBuildPath  { 
146+     fn  new_array ( )  -> ActiveBuildPath  { 
147+         ActiveBuildPath :: default ( ) 
148+     } 
149+ 
150+     fn  new_object ( )  -> ActiveObjectBuildPath  { 
151+         ActiveObjectBuildPath :: default ( ) 
152+     } 
153+ } 
154+ 
155+ impl  MaybeBuildObjectPath  for  ActiveObjectBuildPath  { 
156+     fn  set_key ( & mut  self ,  key :  & str )  { 
157+         self . key  = key. to_string ( ) ; 
158+     } 
159+ 
160+     fn  set_key_path ( & self ,  mut  err :  PythonJsonError )  -> PythonJsonError  { 
161+         err. add ( PathItem :: Key ( self . key . clone ( ) ) ) ; 
162+         err
163+     } 
164+ } 
165+ 
166+ #[ derive( Debug ,  Clone ) ]  
167+ enum  PathItem  { 
168+     Index ( usize ) , 
169+     Key ( String ) , 
170+ } 
171+ 
172+ impl  ToPyObject  for  PathItem  { 
173+     fn  to_object ( & self ,  py :  Python < ' _ > )  -> PyObject  { 
174+         match  self  { 
175+             Self :: Index ( index)  => index. to_object ( py) , 
176+             Self :: Key ( str)  => str. to_object ( py) , 
177+         } 
178+     } 
179+ } 
180+ 
181+ pub  struct  PythonJsonError  { 
182+     pub  error :  JsonError , 
183+     path :  Option < Vec < PathItem > > , 
184+ } 
185+ 
186+ pub ( crate )  type  PythonJsonResult < T >  = Result < T ,  PythonJsonError > ; 
187+ 
188+ impl  From < JsonError >  for  PythonJsonError  { 
189+     fn  from ( error :  JsonError )  -> Self  { 
190+         Self  {  error,  path :  None  } 
191+     } 
192+ } 
193+ 
194+ impl  PythonJsonError  { 
195+     fn  add ( & mut  self ,  path_item :  PathItem )  { 
196+         match  self . path . as_mut ( )  { 
197+             Some ( path)  => path. push ( path_item) , 
198+             None  => self . path  = Some ( vec ! [ path_item] ) , 
199+         } 
200+     } 
201+ } 
0 commit comments