1use crate::{Array, Node, Object, ffi};
7use glib::{
8 object::ObjectType as _,
9 prelude::*,
10 signal::{SignalHandlerId, connect_raw},
11 translate::*,
12};
13use std::{boxed::Box as Box_, pin::Pin};
14
15glib::wrapper! {
16 #[doc(alias = "JsonParser")]
17 pub struct Parser(Object<ffi::JsonParser, ffi::JsonParserClass>);
18
19 match fn {
20 type_ => || ffi::json_parser_get_type(),
21 }
22}
23
24impl Parser {
25 pub const NONE: Option<&'static Parser> = None;
26
27 #[doc(alias = "json_parser_new")]
28 pub fn new() -> Parser {
29 assert_initialized_main_thread!();
30 unsafe { from_glib_full(ffi::json_parser_new()) }
31 }
32
33 #[cfg(feature = "v1_2")]
34 #[cfg_attr(docsrs, doc(cfg(feature = "v1_2")))]
35 #[doc(alias = "json_parser_new_immutable")]
36 pub fn new_immutable() -> Parser {
37 assert_initialized_main_thread!();
38 unsafe { from_glib_full(ffi::json_parser_new_immutable()) }
39 }
40
41 pub fn builder() -> ParserBuilder {
46 ParserBuilder::new()
47 }
48}
49
50impl Default for Parser {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56#[must_use = "The builder must be built to be used"]
61pub struct ParserBuilder {
62 builder: glib::object::ObjectBuilder<'static, Parser>,
63}
64
65impl ParserBuilder {
66 fn new() -> Self {
67 Self {
68 builder: glib::object::Object::builder(),
69 }
70 }
71
72 #[cfg(feature = "v1_2")]
73 #[cfg_attr(docsrs, doc(cfg(feature = "v1_2")))]
74 pub fn immutable(self, immutable: bool) -> Self {
75 Self {
76 builder: self.builder.property("immutable", immutable),
77 }
78 }
79
80 #[cfg(feature = "v1_10")]
81 #[cfg_attr(docsrs, doc(cfg(feature = "v1_10")))]
82 pub fn strict(self, strict: bool) -> Self {
83 Self {
84 builder: self.builder.property("strict", strict),
85 }
86 }
87
88 #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
91 pub fn build(self) -> Parser {
92 assert_initialized_main_thread!();
93 self.builder.build()
94 }
95}
96
97pub trait ParserExt: IsA<Parser> + 'static {
98 #[doc(alias = "json_parser_get_current_line")]
99 #[doc(alias = "get_current_line")]
100 fn current_line(&self) -> u32 {
101 unsafe { ffi::json_parser_get_current_line(self.as_ref().to_glib_none().0) }
102 }
103
104 #[doc(alias = "json_parser_get_current_pos")]
105 #[doc(alias = "get_current_pos")]
106 fn current_pos(&self) -> u32 {
107 unsafe { ffi::json_parser_get_current_pos(self.as_ref().to_glib_none().0) }
108 }
109
110 #[doc(alias = "json_parser_get_root")]
111 #[doc(alias = "get_root")]
112 fn root(&self) -> Option<Node> {
113 unsafe { from_glib_none(ffi::json_parser_get_root(self.as_ref().to_glib_none().0)) }
114 }
115
116 #[cfg(feature = "v1_10")]
117 #[cfg_attr(docsrs, doc(cfg(feature = "v1_10")))]
118 #[doc(alias = "json_parser_get_strict")]
119 #[doc(alias = "get_strict")]
120 #[doc(alias = "strict")]
121 fn is_strict(&self) -> bool {
122 unsafe { from_glib(ffi::json_parser_get_strict(self.as_ref().to_glib_none().0)) }
123 }
124
125 #[doc(alias = "json_parser_has_assignment")]
126 fn has_assignment(&self) -> Option<glib::GString> {
127 unsafe {
128 let variable_name = std::ptr::null_mut();
129 let ret = from_glib(ffi::json_parser_has_assignment(
130 self.as_ref().to_glib_none().0,
131 variable_name,
132 ));
133 if ret {
134 Some(from_glib_none(*variable_name))
135 } else {
136 None
137 }
138 }
139 }
140
141 #[doc(alias = "json_parser_load_from_data")]
142 fn load_from_data(&self, data: &str) -> Result<(), glib::Error> {
143 let length = data.len() as _;
144 unsafe {
145 let mut error = std::ptr::null_mut();
146 let is_ok = ffi::json_parser_load_from_data(
147 self.as_ref().to_glib_none().0,
148 data.to_glib_none().0,
149 length,
150 &mut error,
151 );
152 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
153 if error.is_null() {
154 Ok(())
155 } else {
156 Err(from_glib_full(error))
157 }
158 }
159 }
160
161 #[doc(alias = "json_parser_load_from_file")]
162 fn load_from_file(&self, filename: impl AsRef<std::path::Path>) -> Result<(), glib::Error> {
163 unsafe {
164 let mut error = std::ptr::null_mut();
165 let is_ok = ffi::json_parser_load_from_file(
166 self.as_ref().to_glib_none().0,
167 filename.as_ref().to_glib_none().0,
168 &mut error,
169 );
170 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
171 if error.is_null() {
172 Ok(())
173 } else {
174 Err(from_glib_full(error))
175 }
176 }
177 }
178
179 #[cfg(feature = "v1_6")]
180 #[cfg_attr(docsrs, doc(cfg(feature = "v1_6")))]
181 #[doc(alias = "json_parser_load_from_mapped_file")]
182 fn load_from_mapped_file(
183 &self,
184 filename: impl AsRef<std::path::Path>,
185 ) -> Result<(), glib::Error> {
186 unsafe {
187 let mut error = std::ptr::null_mut();
188 let is_ok = ffi::json_parser_load_from_mapped_file(
189 self.as_ref().to_glib_none().0,
190 filename.as_ref().to_glib_none().0,
191 &mut error,
192 );
193 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
194 if error.is_null() {
195 Ok(())
196 } else {
197 Err(from_glib_full(error))
198 }
199 }
200 }
201
202 #[doc(alias = "json_parser_load_from_stream")]
203 fn load_from_stream(
204 &self,
205 stream: &impl IsA<gio::InputStream>,
206 cancellable: Option<&impl IsA<gio::Cancellable>>,
207 ) -> Result<(), glib::Error> {
208 unsafe {
209 let mut error = std::ptr::null_mut();
210 let is_ok = ffi::json_parser_load_from_stream(
211 self.as_ref().to_glib_none().0,
212 stream.as_ref().to_glib_none().0,
213 cancellable.map(|p| p.as_ref()).to_glib_none().0,
214 &mut error,
215 );
216 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
217 if error.is_null() {
218 Ok(())
219 } else {
220 Err(from_glib_full(error))
221 }
222 }
223 }
224
225 #[doc(alias = "json_parser_load_from_stream_async")]
226 fn load_from_stream_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
227 &self,
228 stream: &impl IsA<gio::InputStream>,
229 cancellable: Option<&impl IsA<gio::Cancellable>>,
230 callback: P,
231 ) {
232 let main_context = glib::MainContext::ref_thread_default();
233 let is_main_context_owner = main_context.is_owner();
234 let has_acquired_main_context = (!is_main_context_owner)
235 .then(|| main_context.acquire().ok())
236 .flatten();
237 assert!(
238 is_main_context_owner || has_acquired_main_context.is_some(),
239 "Async operations only allowed if the thread is owning the MainContext"
240 );
241
242 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
243 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
244 unsafe extern "C" fn load_from_stream_async_trampoline<
245 P: FnOnce(Result<(), glib::Error>) + 'static,
246 >(
247 _source_object: *mut glib::gobject_ffi::GObject,
248 res: *mut gio::ffi::GAsyncResult,
249 user_data: glib::ffi::gpointer,
250 ) {
251 let mut error = std::ptr::null_mut();
252 ffi::json_parser_load_from_stream_finish(_source_object as *mut _, res, &mut error);
253 let result = if error.is_null() {
254 Ok(())
255 } else {
256 Err(from_glib_full(error))
257 };
258 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
259 Box_::from_raw(user_data as *mut _);
260 let callback: P = callback.into_inner();
261 callback(result);
262 }
263 let callback = load_from_stream_async_trampoline::<P>;
264 unsafe {
265 ffi::json_parser_load_from_stream_async(
266 self.as_ref().to_glib_none().0,
267 stream.as_ref().to_glib_none().0,
268 cancellable.map(|p| p.as_ref()).to_glib_none().0,
269 Some(callback),
270 Box_::into_raw(user_data) as *mut _,
271 );
272 }
273 }
274
275 fn load_from_stream_future(
276 &self,
277 stream: &(impl IsA<gio::InputStream> + Clone + 'static),
278 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
279 let stream = stream.clone();
280 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
281 obj.load_from_stream_async(&stream, Some(cancellable), move |res| {
282 send.resolve(res);
283 });
284 }))
285 }
286
287 #[cfg(feature = "v1_10")]
288 #[cfg_attr(docsrs, doc(cfg(feature = "v1_10")))]
289 #[doc(alias = "json_parser_set_strict")]
290 #[doc(alias = "strict")]
291 fn set_strict(&self, strict: bool) {
292 unsafe {
293 ffi::json_parser_set_strict(self.as_ref().to_glib_none().0, strict.into_glib());
294 }
295 }
296
297 #[cfg(feature = "v1_4")]
298 #[cfg_attr(docsrs, doc(cfg(feature = "v1_4")))]
299 #[doc(alias = "json_parser_steal_root")]
300 fn steal_root(&self) -> Option<Node> {
301 unsafe { from_glib_full(ffi::json_parser_steal_root(self.as_ref().to_glib_none().0)) }
302 }
303
304 #[cfg(feature = "v1_2")]
305 #[cfg_attr(docsrs, doc(cfg(feature = "v1_2")))]
306 fn is_immutable(&self) -> bool {
307 ObjectExt::property(self.as_ref(), "immutable")
308 }
309
310 #[cfg_attr(feature = "v1_10", deprecated = "Since 1.10")]
311 #[doc(alias = "array-element")]
312 fn connect_array_element<F: Fn(&Self, &Array, i32) + 'static>(&self, f: F) -> SignalHandlerId {
313 unsafe extern "C" fn array_element_trampoline<
314 P: IsA<Parser>,
315 F: Fn(&P, &Array, i32) + 'static,
316 >(
317 this: *mut ffi::JsonParser,
318 array: *mut ffi::JsonArray,
319 index_: std::ffi::c_int,
320 f: glib::ffi::gpointer,
321 ) {
322 let f: &F = &*(f as *const F);
323 f(
324 Parser::from_glib_borrow(this).unsafe_cast_ref(),
325 &from_glib_borrow(array),
326 index_,
327 )
328 }
329 unsafe {
330 let f: Box_<F> = Box_::new(f);
331 connect_raw(
332 self.as_ptr() as *mut _,
333 c"array-element".as_ptr() as *const _,
334 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
335 array_element_trampoline::<Self, F> as *const (),
336 )),
337 Box_::into_raw(f),
338 )
339 }
340 }
341
342 #[cfg_attr(feature = "v1_10", deprecated = "Since 1.10")]
343 #[doc(alias = "array-end")]
344 fn connect_array_end<F: Fn(&Self, &Array) + 'static>(&self, f: F) -> SignalHandlerId {
345 unsafe extern "C" fn array_end_trampoline<P: IsA<Parser>, F: Fn(&P, &Array) + 'static>(
346 this: *mut ffi::JsonParser,
347 array: *mut ffi::JsonArray,
348 f: glib::ffi::gpointer,
349 ) {
350 let f: &F = &*(f as *const F);
351 f(
352 Parser::from_glib_borrow(this).unsafe_cast_ref(),
353 &from_glib_borrow(array),
354 )
355 }
356 unsafe {
357 let f: Box_<F> = Box_::new(f);
358 connect_raw(
359 self.as_ptr() as *mut _,
360 c"array-end".as_ptr() as *const _,
361 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
362 array_end_trampoline::<Self, F> as *const (),
363 )),
364 Box_::into_raw(f),
365 )
366 }
367 }
368
369 #[cfg_attr(feature = "v1_10", deprecated = "Since 1.10")]
370 #[doc(alias = "array-start")]
371 fn connect_array_start<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
372 unsafe extern "C" fn array_start_trampoline<P: IsA<Parser>, F: Fn(&P) + 'static>(
373 this: *mut ffi::JsonParser,
374 f: glib::ffi::gpointer,
375 ) {
376 let f: &F = &*(f as *const F);
377 f(Parser::from_glib_borrow(this).unsafe_cast_ref())
378 }
379 unsafe {
380 let f: Box_<F> = Box_::new(f);
381 connect_raw(
382 self.as_ptr() as *mut _,
383 c"array-start".as_ptr() as *const _,
384 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
385 array_start_trampoline::<Self, F> as *const (),
386 )),
387 Box_::into_raw(f),
388 )
389 }
390 }
391
392 #[cfg_attr(feature = "v1_10", deprecated = "Since 1.10")]
399 #[doc(alias = "object-end")]
400 fn connect_object_end<F: Fn(&Self, &Object) + 'static>(&self, f: F) -> SignalHandlerId {
401 unsafe extern "C" fn object_end_trampoline<P: IsA<Parser>, F: Fn(&P, &Object) + 'static>(
402 this: *mut ffi::JsonParser,
403 object: *mut ffi::JsonObject,
404 f: glib::ffi::gpointer,
405 ) {
406 let f: &F = &*(f as *const F);
407 f(
408 Parser::from_glib_borrow(this).unsafe_cast_ref(),
409 &from_glib_borrow(object),
410 )
411 }
412 unsafe {
413 let f: Box_<F> = Box_::new(f);
414 connect_raw(
415 self.as_ptr() as *mut _,
416 c"object-end".as_ptr() as *const _,
417 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
418 object_end_trampoline::<Self, F> as *const (),
419 )),
420 Box_::into_raw(f),
421 )
422 }
423 }
424
425 #[cfg_attr(feature = "v1_10", deprecated = "Since 1.10")]
426 #[doc(alias = "object-member")]
427 fn connect_object_member<F: Fn(&Self, &Object, &str) + 'static>(
428 &self,
429 f: F,
430 ) -> SignalHandlerId {
431 unsafe extern "C" fn object_member_trampoline<
432 P: IsA<Parser>,
433 F: Fn(&P, &Object, &str) + 'static,
434 >(
435 this: *mut ffi::JsonParser,
436 object: *mut ffi::JsonObject,
437 member_name: *mut std::ffi::c_char,
438 f: glib::ffi::gpointer,
439 ) {
440 let f: &F = &*(f as *const F);
441 f(
442 Parser::from_glib_borrow(this).unsafe_cast_ref(),
443 &from_glib_borrow(object),
444 &glib::GString::from_glib_borrow(member_name),
445 )
446 }
447 unsafe {
448 let f: Box_<F> = Box_::new(f);
449 connect_raw(
450 self.as_ptr() as *mut _,
451 c"object-member".as_ptr() as *const _,
452 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
453 object_member_trampoline::<Self, F> as *const (),
454 )),
455 Box_::into_raw(f),
456 )
457 }
458 }
459
460 #[cfg_attr(feature = "v1_10", deprecated = "Since 1.10")]
461 #[doc(alias = "object-start")]
462 fn connect_object_start<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
463 unsafe extern "C" fn object_start_trampoline<P: IsA<Parser>, F: Fn(&P) + 'static>(
464 this: *mut ffi::JsonParser,
465 f: glib::ffi::gpointer,
466 ) {
467 let f: &F = &*(f as *const F);
468 f(Parser::from_glib_borrow(this).unsafe_cast_ref())
469 }
470 unsafe {
471 let f: Box_<F> = Box_::new(f);
472 connect_raw(
473 self.as_ptr() as *mut _,
474 c"object-start".as_ptr() as *const _,
475 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
476 object_start_trampoline::<Self, F> as *const (),
477 )),
478 Box_::into_raw(f),
479 )
480 }
481 }
482
483 #[cfg_attr(feature = "v1_10", deprecated = "Since 1.10")]
484 #[doc(alias = "parse-end")]
485 fn connect_parse_end<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
486 unsafe extern "C" fn parse_end_trampoline<P: IsA<Parser>, F: Fn(&P) + 'static>(
487 this: *mut ffi::JsonParser,
488 f: glib::ffi::gpointer,
489 ) {
490 let f: &F = &*(f as *const F);
491 f(Parser::from_glib_borrow(this).unsafe_cast_ref())
492 }
493 unsafe {
494 let f: Box_<F> = Box_::new(f);
495 connect_raw(
496 self.as_ptr() as *mut _,
497 c"parse-end".as_ptr() as *const _,
498 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
499 parse_end_trampoline::<Self, F> as *const (),
500 )),
501 Box_::into_raw(f),
502 )
503 }
504 }
505
506 #[cfg_attr(feature = "v1_10", deprecated = "Since 1.10")]
507 #[doc(alias = "parse-start")]
508 fn connect_parse_start<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
509 unsafe extern "C" fn parse_start_trampoline<P: IsA<Parser>, F: Fn(&P) + 'static>(
510 this: *mut ffi::JsonParser,
511 f: glib::ffi::gpointer,
512 ) {
513 let f: &F = &*(f as *const F);
514 f(Parser::from_glib_borrow(this).unsafe_cast_ref())
515 }
516 unsafe {
517 let f: Box_<F> = Box_::new(f);
518 connect_raw(
519 self.as_ptr() as *mut _,
520 c"parse-start".as_ptr() as *const _,
521 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
522 parse_start_trampoline::<Self, F> as *const (),
523 )),
524 Box_::into_raw(f),
525 )
526 }
527 }
528
529 #[cfg(feature = "v1_10")]
530 #[cfg_attr(docsrs, doc(cfg(feature = "v1_10")))]
531 #[doc(alias = "strict")]
532 fn connect_strict_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
533 unsafe extern "C" fn notify_strict_trampoline<P: IsA<Parser>, F: Fn(&P) + 'static>(
534 this: *mut ffi::JsonParser,
535 _param_spec: glib::ffi::gpointer,
536 f: glib::ffi::gpointer,
537 ) {
538 let f: &F = &*(f as *const F);
539 f(Parser::from_glib_borrow(this).unsafe_cast_ref())
540 }
541 unsafe {
542 let f: Box_<F> = Box_::new(f);
543 connect_raw(
544 self.as_ptr() as *mut _,
545 c"notify::strict".as_ptr() as *const _,
546 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
547 notify_strict_trampoline::<Self, F> as *const (),
548 )),
549 Box_::into_raw(f),
550 )
551 }
552 }
553}
554
555impl<O: IsA<Parser>> ParserExt for O {}