crawlberg 1.4.2 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  // This file is auto-generated by alef. DO NOT EDIT.
2
- // alef:hash:c8bd1f23995c2c54aa56bd9e9dd95391dff81fd7eefe7a65306513caf8564400
2
+ // alef:hash:202c4f469a62d77930ef13ac10e1718ac319e02c448ba94573bae7ab48c1d4ce
3
3
  // Re-generate with: alef generate
4
4
  #![allow(dead_code, unused_imports, unused_variables)]
5
5
  #![allow(
@@ -24,6 +24,52 @@ use magnus::{Error, IntoValueFromNative, Ruby, function, method, prelude::*, try
24
24
  use std::collections::HashMap;
25
25
  use std::sync::Arc;
26
26
 
27
+ /// Run owned Rust work while the calling Ruby thread releases the GVL.
28
+ fn alef_magnus_run_without_gvl<F, T>(callback: F) -> T
29
+ where
30
+ F: FnOnce() -> T,
31
+ {
32
+ struct RunState<F, T> {
33
+ callback: Option<F>,
34
+ result: Option<std::thread::Result<T>>,
35
+ }
36
+
37
+ extern "C" fn run_without_gvl<F, T>(data: *mut std::ffi::c_void) -> *mut std::ffi::c_void
38
+ where
39
+ F: FnOnce() -> T,
40
+ {
41
+ // SAFETY: `data` points to the caller's RunState for the duration of this callback.
42
+ let state = unsafe { &mut *(data as *mut RunState<F, T>) };
43
+ let Some(callback) = state.callback.take() else {
44
+ state.result = Some(Err(Box::new("Alef Magnus callback already consumed")));
45
+ return std::ptr::null_mut();
46
+ };
47
+ state.result = Some(std::panic::catch_unwind(std::panic::AssertUnwindSafe(callback)));
48
+ std::ptr::null_mut()
49
+ }
50
+
51
+ extern "C" fn unblock_run(_data: *mut std::ffi::c_void) {}
52
+
53
+ let mut state = RunState {
54
+ callback: Some(callback),
55
+ result: None,
56
+ };
57
+ // SAFETY: Ruby invokes the callback synchronously, and `state` remains live until it returns.
58
+ unsafe {
59
+ rb_sys::rb_thread_call_without_gvl(
60
+ Some(run_without_gvl::<F, T>),
61
+ &mut state as *mut RunState<F, T> as *mut std::ffi::c_void,
62
+ Some(unblock_run),
63
+ std::ptr::null_mut(),
64
+ );
65
+ }
66
+
67
+ match state.result.expect("Alef Magnus callback did not run") {
68
+ Ok(result) => result,
69
+ Err(payload) => std::panic::resume_unwind(payload),
70
+ }
71
+ }
72
+
27
73
  fn json_to_ruby(handle: &Ruby, val: serde_json::Value) -> magnus::Value {
28
74
  use magnus::IntoValue;
29
75
  match val {
@@ -114,24 +160,51 @@ impl ActionResult {
114
160
  let (kwargs_opt,) = args.optional;
115
161
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
116
162
  Ok(Self {
117
- action_index: kwargs
118
- .get(ruby.to_symbol("action_index"))
119
- .and_then(|v| usize::try_convert(v).ok())
120
- .unwrap_or_default(),
121
- action_type: kwargs
122
- .get(ruby.to_symbol("action_type"))
123
- .and_then(|v| String::try_convert(v).ok())
124
- .unwrap_or_default(),
125
- success: kwargs
126
- .get(ruby.to_symbol("success"))
127
- .and_then(|v| bool::try_convert(v).ok())
128
- .unwrap_or_default(),
129
- data: kwargs
130
- .get(ruby.to_symbol("data"))
131
- .and_then(|v| String::try_convert(v).ok()),
132
- error: kwargs
133
- .get(ruby.to_symbol("error"))
134
- .and_then(|v| String::try_convert(v).ok()),
163
+ action_index: match kwargs.get(ruby.to_symbol("action_index")) {
164
+ Some(v) => usize::try_convert(v).map_err(|e| {
165
+ magnus::Error::new(
166
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
167
+ format!("invalid value for `action_index`: {}", e),
168
+ )
169
+ })?,
170
+ None => Default::default(),
171
+ },
172
+ action_type: match kwargs.get(ruby.to_symbol("action_type")) {
173
+ Some(v) => String::try_convert(v).map_err(|e| {
174
+ magnus::Error::new(
175
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
176
+ format!("invalid value for `action_type`: {}", e),
177
+ )
178
+ })?,
179
+ None => Default::default(),
180
+ },
181
+ success: match kwargs.get(ruby.to_symbol("success")) {
182
+ Some(v) => bool::try_convert(v).map_err(|e| {
183
+ magnus::Error::new(
184
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
185
+ format!("invalid value for `success`: {}", e),
186
+ )
187
+ })?,
188
+ None => Default::default(),
189
+ },
190
+ data: match kwargs.get(ruby.to_symbol("data")).filter(|v| !v.is_nil()) {
191
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
192
+ magnus::Error::new(
193
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
194
+ format!("invalid value for `data`: {}", e),
195
+ )
196
+ })?),
197
+ None => None,
198
+ },
199
+ error: match kwargs.get(ruby.to_symbol("error")).filter(|v| !v.is_nil()) {
200
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
201
+ magnus::Error::new(
202
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
203
+ format!("invalid value for `error`: {}", e),
204
+ )
205
+ })?),
206
+ None => None,
207
+ },
135
208
  })
136
209
  }
137
210
 
@@ -208,22 +281,51 @@ impl ArticleMetadata {
208
281
  let (kwargs_opt,) = args.optional;
209
282
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
210
283
  Ok(Self {
211
- published_time: kwargs
212
- .get(ruby.to_symbol("published_time"))
213
- .and_then(|v| String::try_convert(v).ok()),
214
- modified_time: kwargs
215
- .get(ruby.to_symbol("modified_time"))
216
- .and_then(|v| String::try_convert(v).ok()),
217
- author: kwargs
218
- .get(ruby.to_symbol("author"))
219
- .and_then(|v| String::try_convert(v).ok()),
220
- section: kwargs
221
- .get(ruby.to_symbol("section"))
222
- .and_then(|v| String::try_convert(v).ok()),
223
- tags: kwargs
224
- .get(ruby.to_symbol("tags"))
225
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
226
- .unwrap_or_default(),
284
+ published_time: match kwargs.get(ruby.to_symbol("published_time")).filter(|v| !v.is_nil()) {
285
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
286
+ magnus::Error::new(
287
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
288
+ format!("invalid value for `published_time`: {}", e),
289
+ )
290
+ })?),
291
+ None => None,
292
+ },
293
+ modified_time: match kwargs.get(ruby.to_symbol("modified_time")).filter(|v| !v.is_nil()) {
294
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
295
+ magnus::Error::new(
296
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
297
+ format!("invalid value for `modified_time`: {}", e),
298
+ )
299
+ })?),
300
+ None => None,
301
+ },
302
+ author: match kwargs.get(ruby.to_symbol("author")).filter(|v| !v.is_nil()) {
303
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
304
+ magnus::Error::new(
305
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
306
+ format!("invalid value for `author`: {}", e),
307
+ )
308
+ })?),
309
+ None => None,
310
+ },
311
+ section: match kwargs.get(ruby.to_symbol("section")).filter(|v| !v.is_nil()) {
312
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
313
+ magnus::Error::new(
314
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
315
+ format!("invalid value for `section`: {}", e),
316
+ )
317
+ })?),
318
+ None => None,
319
+ },
320
+ tags: match kwargs.get(ruby.to_symbol("tags")) {
321
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
322
+ magnus::Error::new(
323
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
324
+ format!("invalid value for `tags`: {}", e),
325
+ )
326
+ })?,
327
+ None => Default::default(),
328
+ },
227
329
  })
228
330
  }
229
331
 
@@ -298,16 +400,33 @@ impl BatchCrawlResult {
298
400
  let (kwargs_opt,) = args.optional;
299
401
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
300
402
  Ok(Self {
301
- url: kwargs
302
- .get(ruby.to_symbol("url"))
303
- .and_then(|v| String::try_convert(v).ok())
304
- .unwrap_or_default(),
305
- result: kwargs
306
- .get(ruby.to_symbol("result"))
307
- .and_then(|v| CrawlResult::try_convert(v).ok()),
308
- error: kwargs
309
- .get(ruby.to_symbol("error"))
310
- .and_then(|v| String::try_convert(v).ok()),
403
+ url: match kwargs.get(ruby.to_symbol("url")) {
404
+ Some(v) => String::try_convert(v).map_err(|e| {
405
+ magnus::Error::new(
406
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
407
+ format!("invalid value for `url`: {}", e),
408
+ )
409
+ })?,
410
+ None => Default::default(),
411
+ },
412
+ result: match kwargs.get(ruby.to_symbol("result")).filter(|v| !v.is_nil()) {
413
+ Some(v) => Some(CrawlResult::try_convert(v).map_err(|e| {
414
+ magnus::Error::new(
415
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
416
+ format!("invalid value for `result`: {}", e),
417
+ )
418
+ })?),
419
+ None => None,
420
+ },
421
+ error: match kwargs.get(ruby.to_symbol("error")).filter(|v| !v.is_nil()) {
422
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
423
+ magnus::Error::new(
424
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
425
+ format!("invalid value for `error`: {}", e),
426
+ )
427
+ })?),
428
+ None => None,
429
+ },
311
430
  })
312
431
  }
313
432
 
@@ -375,22 +494,42 @@ impl BatchCrawlResults {
375
494
  let (kwargs_opt,) = args.optional;
376
495
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
377
496
  Ok(Self {
378
- results: kwargs
379
- .get(ruby.to_symbol("results"))
380
- .and_then(|v| <Vec<BatchCrawlResult>>::try_convert(v).ok())
381
- .unwrap_or_default(),
382
- total_count: kwargs
383
- .get(ruby.to_symbol("total_count"))
384
- .and_then(|v| usize::try_convert(v).ok())
385
- .unwrap_or_default(),
386
- completed_count: kwargs
387
- .get(ruby.to_symbol("completed_count"))
388
- .and_then(|v| usize::try_convert(v).ok())
389
- .unwrap_or_default(),
390
- failed_count: kwargs
391
- .get(ruby.to_symbol("failed_count"))
392
- .and_then(|v| usize::try_convert(v).ok())
393
- .unwrap_or_default(),
497
+ results: match kwargs.get(ruby.to_symbol("results")) {
498
+ Some(v) => <Vec<BatchCrawlResult>>::try_convert(v).map_err(|e| {
499
+ magnus::Error::new(
500
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
501
+ format!("invalid value for `results`: {}", e),
502
+ )
503
+ })?,
504
+ None => Default::default(),
505
+ },
506
+ total_count: match kwargs.get(ruby.to_symbol("total_count")) {
507
+ Some(v) => usize::try_convert(v).map_err(|e| {
508
+ magnus::Error::new(
509
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
510
+ format!("invalid value for `total_count`: {}", e),
511
+ )
512
+ })?,
513
+ None => Default::default(),
514
+ },
515
+ completed_count: match kwargs.get(ruby.to_symbol("completed_count")) {
516
+ Some(v) => usize::try_convert(v).map_err(|e| {
517
+ magnus::Error::new(
518
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
519
+ format!("invalid value for `completed_count`: {}", e),
520
+ )
521
+ })?,
522
+ None => Default::default(),
523
+ },
524
+ failed_count: match kwargs.get(ruby.to_symbol("failed_count")) {
525
+ Some(v) => usize::try_convert(v).map_err(|e| {
526
+ magnus::Error::new(
527
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
528
+ format!("invalid value for `failed_count`: {}", e),
529
+ )
530
+ })?,
531
+ None => Default::default(),
532
+ },
394
533
  })
395
534
  }
396
535
 
@@ -411,6 +550,7 @@ impl BatchCrawlResults {
411
550
  }
412
551
  }
413
552
 
553
+ #[cfg(not(target_arch = "wasm32"))]
414
554
  #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
415
555
  #[serde(default)]
416
556
  #[magnus::wrap(class = "Crawlberg::BatchCrawlStreamRequest")]
@@ -418,8 +558,10 @@ pub struct BatchCrawlStreamRequest {
418
558
  urls: Vec<String>,
419
559
  }
420
560
 
561
+ #[cfg(not(target_arch = "wasm32"))]
421
562
  unsafe impl IntoValueFromNative for BatchCrawlStreamRequest {}
422
563
 
564
+ #[cfg(not(target_arch = "wasm32"))]
423
565
  impl magnus::TryConvert for BatchCrawlStreamRequest {
424
566
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
425
567
  if let Ok(r) = <&BatchCrawlStreamRequest as magnus::TryConvert>::try_convert(val) {
@@ -444,14 +586,17 @@ impl magnus::TryConvert for BatchCrawlStreamRequest {
444
586
  }
445
587
  }
446
588
 
589
+ #[cfg(not(target_arch = "wasm32"))]
447
590
  unsafe impl TryConvertOwned for BatchCrawlStreamRequest {}
448
591
 
592
+ #[cfg(not(target_arch = "wasm32"))]
449
593
  impl Default for BatchCrawlStreamRequest {
450
594
  fn default() -> Self {
451
595
  crawlberg::BatchCrawlStreamRequest::default().into()
452
596
  }
453
597
  }
454
598
 
599
+ #[cfg(not(target_arch = "wasm32"))]
455
600
  impl BatchCrawlStreamRequest {
456
601
  fn new(args: &[magnus::Value]) -> Result<Self, magnus::Error> {
457
602
  let ruby = unsafe { magnus::Ruby::get_unchecked() };
@@ -459,10 +604,15 @@ impl BatchCrawlStreamRequest {
459
604
  let (kwargs_opt,) = args.optional;
460
605
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
461
606
  Ok(Self {
462
- urls: kwargs
463
- .get(ruby.to_symbol("urls"))
464
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
465
- .unwrap_or_default(),
607
+ urls: match kwargs.get(ruby.to_symbol("urls")) {
608
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
609
+ magnus::Error::new(
610
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
611
+ format!("invalid value for `urls`: {}", e),
612
+ )
613
+ })?,
614
+ None => Default::default(),
615
+ },
466
616
  })
467
617
  }
468
618
 
@@ -521,16 +671,33 @@ impl BatchScrapeResult {
521
671
  let (kwargs_opt,) = args.optional;
522
672
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
523
673
  Ok(Self {
524
- url: kwargs
525
- .get(ruby.to_symbol("url"))
526
- .and_then(|v| String::try_convert(v).ok())
527
- .unwrap_or_default(),
528
- result: kwargs
529
- .get(ruby.to_symbol("result"))
530
- .and_then(|v| ScrapeResult::try_convert(v).ok()),
531
- error: kwargs
532
- .get(ruby.to_symbol("error"))
533
- .and_then(|v| String::try_convert(v).ok()),
674
+ url: match kwargs.get(ruby.to_symbol("url")) {
675
+ Some(v) => String::try_convert(v).map_err(|e| {
676
+ magnus::Error::new(
677
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
678
+ format!("invalid value for `url`: {}", e),
679
+ )
680
+ })?,
681
+ None => Default::default(),
682
+ },
683
+ result: match kwargs.get(ruby.to_symbol("result")).filter(|v| !v.is_nil()) {
684
+ Some(v) => Some(ScrapeResult::try_convert(v).map_err(|e| {
685
+ magnus::Error::new(
686
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
687
+ format!("invalid value for `result`: {}", e),
688
+ )
689
+ })?),
690
+ None => None,
691
+ },
692
+ error: match kwargs.get(ruby.to_symbol("error")).filter(|v| !v.is_nil()) {
693
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
694
+ magnus::Error::new(
695
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
696
+ format!("invalid value for `error`: {}", e),
697
+ )
698
+ })?),
699
+ None => None,
700
+ },
534
701
  })
535
702
  }
536
703
 
@@ -598,22 +765,42 @@ impl BatchScrapeResults {
598
765
  let (kwargs_opt,) = args.optional;
599
766
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
600
767
  Ok(Self {
601
- results: kwargs
602
- .get(ruby.to_symbol("results"))
603
- .and_then(|v| <Vec<BatchScrapeResult>>::try_convert(v).ok())
604
- .unwrap_or_default(),
605
- total_count: kwargs
606
- .get(ruby.to_symbol("total_count"))
607
- .and_then(|v| usize::try_convert(v).ok())
608
- .unwrap_or_default(),
609
- completed_count: kwargs
610
- .get(ruby.to_symbol("completed_count"))
611
- .and_then(|v| usize::try_convert(v).ok())
612
- .unwrap_or_default(),
613
- failed_count: kwargs
614
- .get(ruby.to_symbol("failed_count"))
615
- .and_then(|v| usize::try_convert(v).ok())
616
- .unwrap_or_default(),
768
+ results: match kwargs.get(ruby.to_symbol("results")) {
769
+ Some(v) => <Vec<BatchScrapeResult>>::try_convert(v).map_err(|e| {
770
+ magnus::Error::new(
771
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
772
+ format!("invalid value for `results`: {}", e),
773
+ )
774
+ })?,
775
+ None => Default::default(),
776
+ },
777
+ total_count: match kwargs.get(ruby.to_symbol("total_count")) {
778
+ Some(v) => usize::try_convert(v).map_err(|e| {
779
+ magnus::Error::new(
780
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
781
+ format!("invalid value for `total_count`: {}", e),
782
+ )
783
+ })?,
784
+ None => Default::default(),
785
+ },
786
+ completed_count: match kwargs.get(ruby.to_symbol("completed_count")) {
787
+ Some(v) => usize::try_convert(v).map_err(|e| {
788
+ magnus::Error::new(
789
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
790
+ format!("invalid value for `completed_count`: {}", e),
791
+ )
792
+ })?,
793
+ None => Default::default(),
794
+ },
795
+ failed_count: match kwargs.get(ruby.to_symbol("failed_count")) {
796
+ Some(v) => usize::try_convert(v).map_err(|e| {
797
+ magnus::Error::new(
798
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
799
+ format!("invalid value for `failed_count`: {}", e),
800
+ )
801
+ })?,
802
+ None => Default::default(),
803
+ },
617
804
  })
618
805
  }
619
806
 
@@ -634,7 +821,7 @@ impl BatchScrapeResults {
634
821
  }
635
822
  }
636
823
 
637
- #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
824
+ #[derive(Clone, Debug, serde::Serialize)]
638
825
  #[serde(default)]
639
826
  #[magnus::wrap(class = "Crawlberg::BrowserConfig")]
640
827
  pub struct BrowserConfig {
@@ -681,6 +868,14 @@ impl magnus::TryConvert for BrowserConfig {
681
868
  }
682
869
 
683
870
  unsafe impl TryConvertOwned for BrowserConfig {}
871
+ impl<'de> serde::Deserialize<'de> for BrowserConfig {
872
+ fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
873
+ where
874
+ D: serde::Deserializer<'de>,
875
+ {
876
+ <crawlberg::BrowserConfig as serde::Deserialize>::deserialize(deserializer).map(Into::into)
877
+ }
878
+ }
684
879
 
685
880
  impl Default for BrowserConfig {
686
881
  fn default() -> Self {
@@ -695,52 +890,123 @@ impl BrowserConfig {
695
890
  let (kwargs_opt,) = args.optional;
696
891
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
697
892
  Ok(Self {
698
- mode: kwargs
699
- .get(ruby.to_symbol("mode"))
700
- .and_then(|v| BrowserMode::try_convert(v).ok())
701
- .unwrap_or(BrowserMode::Auto),
702
- backend: kwargs
703
- .get(ruby.to_symbol("backend"))
704
- .and_then(|v| BrowserBackend::try_convert(v).ok())
705
- .unwrap_or(BrowserBackend::Chromiumoxide),
706
- endpoint: kwargs
707
- .get(ruby.to_symbol("endpoint"))
708
- .and_then(|v| String::try_convert(v).ok()),
709
- timeout: kwargs
710
- .get(ruby.to_symbol("timeout"))
711
- .and_then(|v| u64::try_convert(v).ok())
712
- .unwrap_or(30000),
713
- wait: kwargs
714
- .get(ruby.to_symbol("wait"))
715
- .and_then(|v| BrowserWait::try_convert(v).ok())
716
- .unwrap_or(BrowserWait::NetworkIdle),
717
- wait_selector: kwargs
718
- .get(ruby.to_symbol("wait_selector"))
719
- .and_then(|v| String::try_convert(v).ok()),
720
- extra_wait: kwargs
721
- .get(ruby.to_symbol("extra_wait"))
722
- .and_then(|v| u64::try_convert(v).ok()),
723
- proxy: kwargs
724
- .get(ruby.to_symbol("proxy"))
725
- .and_then(|v| ProxyConfig::try_convert(v).ok()),
726
- block_url_patterns: kwargs
727
- .get(ruby.to_symbol("block_url_patterns"))
728
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
729
- .unwrap_or_default(),
730
- eval_script: kwargs
731
- .get(ruby.to_symbol("eval_script"))
732
- .and_then(|v| String::try_convert(v).ok()),
733
- robots_user_agent: kwargs
734
- .get(ruby.to_symbol("robots_user_agent"))
735
- .and_then(|v| String::try_convert(v).ok()),
736
- capture_network_events: kwargs
737
- .get(ruby.to_symbol("capture_network_events"))
738
- .and_then(|v| bool::try_convert(v).ok())
739
- .unwrap_or(false),
740
- session_affinity: kwargs
741
- .get(ruby.to_symbol("session_affinity"))
742
- .and_then(|v| bool::try_convert(v).ok())
743
- .unwrap_or(true),
893
+ mode: match kwargs.get(ruby.to_symbol("mode")) {
894
+ Some(v) => BrowserMode::try_convert(v).map_err(|e| {
895
+ magnus::Error::new(
896
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
897
+ format!("invalid value for `mode`: {}", e),
898
+ )
899
+ })?,
900
+ None => BrowserMode::Auto,
901
+ },
902
+ backend: match kwargs.get(ruby.to_symbol("backend")) {
903
+ Some(v) => BrowserBackend::try_convert(v).map_err(|e| {
904
+ magnus::Error::new(
905
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
906
+ format!("invalid value for `backend`: {}", e),
907
+ )
908
+ })?,
909
+ None => BrowserBackend::Chromiumoxide,
910
+ },
911
+ endpoint: match kwargs.get(ruby.to_symbol("endpoint")).filter(|v| !v.is_nil()) {
912
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
913
+ magnus::Error::new(
914
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
915
+ format!("invalid value for `endpoint`: {}", e),
916
+ )
917
+ })?),
918
+ None => None,
919
+ },
920
+ timeout: match kwargs.get(ruby.to_symbol("timeout")) {
921
+ Some(v) => u64::try_convert(v).map_err(|e| {
922
+ magnus::Error::new(
923
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
924
+ format!("invalid value for `timeout`: {}", e),
925
+ )
926
+ })?,
927
+ None => 30000,
928
+ },
929
+ wait: match kwargs.get(ruby.to_symbol("wait")) {
930
+ Some(v) => BrowserWait::try_convert(v).map_err(|e| {
931
+ magnus::Error::new(
932
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
933
+ format!("invalid value for `wait`: {}", e),
934
+ )
935
+ })?,
936
+ None => BrowserWait::NetworkIdle,
937
+ },
938
+ wait_selector: match kwargs.get(ruby.to_symbol("wait_selector")).filter(|v| !v.is_nil()) {
939
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
940
+ magnus::Error::new(
941
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
942
+ format!("invalid value for `wait_selector`: {}", e),
943
+ )
944
+ })?),
945
+ None => None,
946
+ },
947
+ extra_wait: match kwargs.get(ruby.to_symbol("extra_wait")).filter(|v| !v.is_nil()) {
948
+ Some(v) => Some(u64::try_convert(v).map_err(|e| {
949
+ magnus::Error::new(
950
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
951
+ format!("invalid value for `extra_wait`: {}", e),
952
+ )
953
+ })?),
954
+ None => None,
955
+ },
956
+ proxy: match kwargs.get(ruby.to_symbol("proxy")).filter(|v| !v.is_nil()) {
957
+ Some(v) => Some(ProxyConfig::try_convert(v).map_err(|e| {
958
+ magnus::Error::new(
959
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
960
+ format!("invalid value for `proxy`: {}", e),
961
+ )
962
+ })?),
963
+ None => None,
964
+ },
965
+ block_url_patterns: match kwargs.get(ruby.to_symbol("block_url_patterns")) {
966
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
967
+ magnus::Error::new(
968
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
969
+ format!("invalid value for `block_url_patterns`: {}", e),
970
+ )
971
+ })?,
972
+ None => Default::default(),
973
+ },
974
+ eval_script: match kwargs.get(ruby.to_symbol("eval_script")).filter(|v| !v.is_nil()) {
975
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
976
+ magnus::Error::new(
977
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
978
+ format!("invalid value for `eval_script`: {}", e),
979
+ )
980
+ })?),
981
+ None => None,
982
+ },
983
+ robots_user_agent: match kwargs.get(ruby.to_symbol("robots_user_agent")).filter(|v| !v.is_nil()) {
984
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
985
+ magnus::Error::new(
986
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
987
+ format!("invalid value for `robots_user_agent`: {}", e),
988
+ )
989
+ })?),
990
+ None => None,
991
+ },
992
+ capture_network_events: match kwargs.get(ruby.to_symbol("capture_network_events")) {
993
+ Some(v) => bool::try_convert(v).map_err(|e| {
994
+ magnus::Error::new(
995
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
996
+ format!("invalid value for `capture_network_events`: {}", e),
997
+ )
998
+ })?,
999
+ None => false,
1000
+ },
1001
+ session_affinity: match kwargs.get(ruby.to_symbol("session_affinity")) {
1002
+ Some(v) => bool::try_convert(v).map_err(|e| {
1003
+ magnus::Error::new(
1004
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1005
+ format!("invalid value for `session_affinity`: {}", e),
1006
+ )
1007
+ })?,
1008
+ None => true,
1009
+ },
744
1010
  })
745
1011
  }
746
1012
 
@@ -797,7 +1063,7 @@ impl BrowserConfig {
797
1063
  }
798
1064
  }
799
1065
 
800
- #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
1066
+ #[derive(Clone, Debug, serde::Serialize)]
801
1067
  #[serde(default)]
802
1068
  #[magnus::wrap(class = "Crawlberg::BrowserExtras")]
803
1069
  pub struct BrowserExtras {
@@ -833,6 +1099,14 @@ impl magnus::TryConvert for BrowserExtras {
833
1099
  }
834
1100
 
835
1101
  unsafe impl TryConvertOwned for BrowserExtras {}
1102
+ impl<'de> serde::Deserialize<'de> for BrowserExtras {
1103
+ fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
1104
+ where
1105
+ D: serde::Deserializer<'de>,
1106
+ {
1107
+ <crawlberg::BrowserExtras as serde::Deserialize>::deserialize(deserializer).map(Into::into)
1108
+ }
1109
+ }
836
1110
 
837
1111
  impl Default for BrowserExtras {
838
1112
  fn default() -> Self {
@@ -847,17 +1121,33 @@ impl BrowserExtras {
847
1121
  let (kwargs_opt,) = args.optional;
848
1122
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
849
1123
  Ok(Self {
850
- eval_result: kwargs
851
- .get(ruby.to_symbol("eval_result"))
852
- .and_then(|v| String::try_convert(v).ok()),
853
- network_events: kwargs
854
- .get(ruby.to_symbol("network_events"))
855
- .and_then(|v| <Vec<ResponseMeta>>::try_convert(v).ok())
856
- .unwrap_or_default(),
857
- cookies: kwargs
858
- .get(ruby.to_symbol("cookies"))
859
- .and_then(|v| <Vec<CookieInfo>>::try_convert(v).ok())
860
- .unwrap_or_default(),
1124
+ eval_result: match kwargs.get(ruby.to_symbol("eval_result")).filter(|v| !v.is_nil()) {
1125
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
1126
+ magnus::Error::new(
1127
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1128
+ format!("invalid value for `eval_result`: {}", e),
1129
+ )
1130
+ })?),
1131
+ None => None,
1132
+ },
1133
+ network_events: match kwargs.get(ruby.to_symbol("network_events")) {
1134
+ Some(v) => <Vec<ResponseMeta>>::try_convert(v).map_err(|e| {
1135
+ magnus::Error::new(
1136
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1137
+ format!("invalid value for `network_events`: {}", e),
1138
+ )
1139
+ })?,
1140
+ None => Default::default(),
1141
+ },
1142
+ cookies: match kwargs.get(ruby.to_symbol("cookies")) {
1143
+ Some(v) => <Vec<CookieInfo>>::try_convert(v).map_err(|e| {
1144
+ magnus::Error::new(
1145
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1146
+ format!("invalid value for `cookies`: {}", e),
1147
+ )
1148
+ })?,
1149
+ None => Default::default(),
1150
+ },
861
1151
  })
862
1152
  }
863
1153
 
@@ -924,18 +1214,33 @@ impl CitationReference {
924
1214
  let (kwargs_opt,) = args.optional;
925
1215
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
926
1216
  Ok(Self {
927
- index: kwargs
928
- .get(ruby.to_symbol("index"))
929
- .and_then(|v| usize::try_convert(v).ok())
930
- .unwrap_or_default(),
931
- url: kwargs
932
- .get(ruby.to_symbol("url"))
933
- .and_then(|v| String::try_convert(v).ok())
934
- .unwrap_or_default(),
935
- text: kwargs
936
- .get(ruby.to_symbol("text"))
937
- .and_then(|v| String::try_convert(v).ok())
938
- .unwrap_or_default(),
1217
+ index: match kwargs.get(ruby.to_symbol("index")) {
1218
+ Some(v) => usize::try_convert(v).map_err(|e| {
1219
+ magnus::Error::new(
1220
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1221
+ format!("invalid value for `index`: {}", e),
1222
+ )
1223
+ })?,
1224
+ None => Default::default(),
1225
+ },
1226
+ url: match kwargs.get(ruby.to_symbol("url")) {
1227
+ Some(v) => String::try_convert(v).map_err(|e| {
1228
+ magnus::Error::new(
1229
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1230
+ format!("invalid value for `url`: {}", e),
1231
+ )
1232
+ })?,
1233
+ None => Default::default(),
1234
+ },
1235
+ text: match kwargs.get(ruby.to_symbol("text")) {
1236
+ Some(v) => String::try_convert(v).map_err(|e| {
1237
+ magnus::Error::new(
1238
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1239
+ format!("invalid value for `text`: {}", e),
1240
+ )
1241
+ })?,
1242
+ None => Default::default(),
1243
+ },
939
1244
  })
940
1245
  }
941
1246
 
@@ -1001,14 +1306,24 @@ impl CitationResult {
1001
1306
  let (kwargs_opt,) = args.optional;
1002
1307
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
1003
1308
  Ok(Self {
1004
- content: kwargs
1005
- .get(ruby.to_symbol("content"))
1006
- .and_then(|v| String::try_convert(v).ok())
1007
- .unwrap_or_default(),
1008
- references: kwargs
1009
- .get(ruby.to_symbol("references"))
1010
- .and_then(|v| <Vec<CitationReference>>::try_convert(v).ok())
1011
- .unwrap_or_default(),
1309
+ content: match kwargs.get(ruby.to_symbol("content")) {
1310
+ Some(v) => String::try_convert(v).map_err(|e| {
1311
+ magnus::Error::new(
1312
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1313
+ format!("invalid value for `content`: {}", e),
1314
+ )
1315
+ })?,
1316
+ None => Default::default(),
1317
+ },
1318
+ references: match kwargs.get(ruby.to_symbol("references")) {
1319
+ Some(v) => <Vec<CitationReference>>::try_convert(v).map_err(|e| {
1320
+ magnus::Error::new(
1321
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1322
+ format!("invalid value for `references`: {}", e),
1323
+ )
1324
+ })?,
1325
+ None => Default::default(),
1326
+ },
1012
1327
  })
1013
1328
  }
1014
1329
 
@@ -1026,7 +1341,7 @@ impl CitationResult {
1026
1341
  }
1027
1342
  }
1028
1343
 
1029
- #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
1344
+ #[derive(Clone, Debug, serde::Serialize)]
1030
1345
  #[serde(default)]
1031
1346
  #[magnus::wrap(class = "Crawlberg::ContentConfig")]
1032
1347
  pub struct ContentConfig {
@@ -1071,6 +1386,14 @@ impl magnus::TryConvert for ContentConfig {
1071
1386
  }
1072
1387
 
1073
1388
  unsafe impl TryConvertOwned for ContentConfig {}
1389
+ impl<'de> serde::Deserialize<'de> for ContentConfig {
1390
+ fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
1391
+ where
1392
+ D: serde::Deserializer<'de>,
1393
+ {
1394
+ <crawlberg::ContentConfig as serde::Deserialize>::deserialize(deserializer).map(Into::into)
1395
+ }
1396
+ }
1074
1397
 
1075
1398
  impl Default for ContentConfig {
1076
1399
  fn default() -> Self {
@@ -1085,53 +1408,114 @@ impl ContentConfig {
1085
1408
  let (kwargs_opt,) = args.optional;
1086
1409
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
1087
1410
  Ok(Self {
1088
- output_format: kwargs
1089
- .get(ruby.to_symbol("output_format"))
1090
- .and_then(|v| String::try_convert(v).ok())
1091
- .unwrap_or("markdown".to_string()),
1092
- preprocessing_preset: kwargs
1093
- .get(ruby.to_symbol("preprocessing_preset"))
1094
- .and_then(|v| String::try_convert(v).ok())
1095
- .unwrap_or("standard".to_string()),
1096
- remove_navigation: kwargs
1097
- .get(ruby.to_symbol("remove_navigation"))
1098
- .and_then(|v| bool::try_convert(v).ok())
1099
- .unwrap_or(true),
1100
- remove_forms: kwargs
1101
- .get(ruby.to_symbol("remove_forms"))
1102
- .and_then(|v| bool::try_convert(v).ok())
1103
- .unwrap_or(true),
1104
- strip_tags: kwargs
1105
- .get(ruby.to_symbol("strip_tags"))
1106
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
1107
- .unwrap_or_default(),
1108
- preserve_tags: kwargs
1109
- .get(ruby.to_symbol("preserve_tags"))
1110
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
1111
- .unwrap_or_default(),
1112
- exclude_selectors: kwargs
1113
- .get(ruby.to_symbol("exclude_selectors"))
1114
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
1115
- .unwrap_or(vec!["noscript".to_string()]),
1116
- skip_images: kwargs
1117
- .get(ruby.to_symbol("skip_images"))
1118
- .and_then(|v| bool::try_convert(v).ok())
1119
- .unwrap_or(false),
1120
- max_depth: kwargs
1121
- .get(ruby.to_symbol("max_depth"))
1122
- .and_then(|v| usize::try_convert(v).ok()),
1123
- wrap: kwargs
1124
- .get(ruby.to_symbol("wrap"))
1125
- .and_then(|v| bool::try_convert(v).ok())
1126
- .unwrap_or(false),
1127
- wrap_width: kwargs
1128
- .get(ruby.to_symbol("wrap_width"))
1129
- .and_then(|v| usize::try_convert(v).ok())
1130
- .unwrap_or(80),
1131
- include_document_structure: kwargs
1132
- .get(ruby.to_symbol("include_document_structure"))
1133
- .and_then(|v| bool::try_convert(v).ok())
1134
- .unwrap_or(true),
1411
+ output_format: match kwargs.get(ruby.to_symbol("output_format")) {
1412
+ Some(v) => String::try_convert(v).map_err(|e| {
1413
+ magnus::Error::new(
1414
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1415
+ format!("invalid value for `output_format`: {}", e),
1416
+ )
1417
+ })?,
1418
+ None => "markdown".to_string(),
1419
+ },
1420
+ preprocessing_preset: match kwargs.get(ruby.to_symbol("preprocessing_preset")) {
1421
+ Some(v) => String::try_convert(v).map_err(|e| {
1422
+ magnus::Error::new(
1423
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1424
+ format!("invalid value for `preprocessing_preset`: {}", e),
1425
+ )
1426
+ })?,
1427
+ None => "standard".to_string(),
1428
+ },
1429
+ remove_navigation: match kwargs.get(ruby.to_symbol("remove_navigation")) {
1430
+ Some(v) => bool::try_convert(v).map_err(|e| {
1431
+ magnus::Error::new(
1432
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1433
+ format!("invalid value for `remove_navigation`: {}", e),
1434
+ )
1435
+ })?,
1436
+ None => true,
1437
+ },
1438
+ remove_forms: match kwargs.get(ruby.to_symbol("remove_forms")) {
1439
+ Some(v) => bool::try_convert(v).map_err(|e| {
1440
+ magnus::Error::new(
1441
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1442
+ format!("invalid value for `remove_forms`: {}", e),
1443
+ )
1444
+ })?,
1445
+ None => true,
1446
+ },
1447
+ strip_tags: match kwargs.get(ruby.to_symbol("strip_tags")) {
1448
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
1449
+ magnus::Error::new(
1450
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1451
+ format!("invalid value for `strip_tags`: {}", e),
1452
+ )
1453
+ })?,
1454
+ None => Default::default(),
1455
+ },
1456
+ preserve_tags: match kwargs.get(ruby.to_symbol("preserve_tags")) {
1457
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
1458
+ magnus::Error::new(
1459
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1460
+ format!("invalid value for `preserve_tags`: {}", e),
1461
+ )
1462
+ })?,
1463
+ None => Default::default(),
1464
+ },
1465
+ exclude_selectors: match kwargs.get(ruby.to_symbol("exclude_selectors")) {
1466
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
1467
+ magnus::Error::new(
1468
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1469
+ format!("invalid value for `exclude_selectors`: {}", e),
1470
+ )
1471
+ })?,
1472
+ None => vec!["noscript".to_string()],
1473
+ },
1474
+ skip_images: match kwargs.get(ruby.to_symbol("skip_images")) {
1475
+ Some(v) => bool::try_convert(v).map_err(|e| {
1476
+ magnus::Error::new(
1477
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1478
+ format!("invalid value for `skip_images`: {}", e),
1479
+ )
1480
+ })?,
1481
+ None => false,
1482
+ },
1483
+ max_depth: match kwargs.get(ruby.to_symbol("max_depth")).filter(|v| !v.is_nil()) {
1484
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
1485
+ magnus::Error::new(
1486
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1487
+ format!("invalid value for `max_depth`: {}", e),
1488
+ )
1489
+ })?),
1490
+ None => None,
1491
+ },
1492
+ wrap: match kwargs.get(ruby.to_symbol("wrap")) {
1493
+ Some(v) => bool::try_convert(v).map_err(|e| {
1494
+ magnus::Error::new(
1495
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1496
+ format!("invalid value for `wrap`: {}", e),
1497
+ )
1498
+ })?,
1499
+ None => false,
1500
+ },
1501
+ wrap_width: match kwargs.get(ruby.to_symbol("wrap_width")) {
1502
+ Some(v) => usize::try_convert(v).map_err(|e| {
1503
+ magnus::Error::new(
1504
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1505
+ format!("invalid value for `wrap_width`: {}", e),
1506
+ )
1507
+ })?,
1508
+ None => 80,
1509
+ },
1510
+ include_document_structure: match kwargs.get(ruby.to_symbol("include_document_structure")) {
1511
+ Some(v) => bool::try_convert(v).map_err(|e| {
1512
+ magnus::Error::new(
1513
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1514
+ format!("invalid value for `include_document_structure`: {}", e),
1515
+ )
1516
+ })?,
1517
+ None => true,
1518
+ },
1135
1519
  })
1136
1520
  }
1137
1521
 
@@ -1235,20 +1619,42 @@ impl CookieInfo {
1235
1619
  let (kwargs_opt,) = args.optional;
1236
1620
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
1237
1621
  Ok(Self {
1238
- name: kwargs
1239
- .get(ruby.to_symbol("name"))
1240
- .and_then(|v| String::try_convert(v).ok())
1241
- .unwrap_or_default(),
1242
- value: kwargs
1243
- .get(ruby.to_symbol("value"))
1244
- .and_then(|v| String::try_convert(v).ok())
1245
- .unwrap_or_default(),
1246
- domain: kwargs
1247
- .get(ruby.to_symbol("domain"))
1248
- .and_then(|v| String::try_convert(v).ok()),
1249
- path: kwargs
1250
- .get(ruby.to_symbol("path"))
1251
- .and_then(|v| String::try_convert(v).ok()),
1622
+ name: match kwargs.get(ruby.to_symbol("name")) {
1623
+ Some(v) => String::try_convert(v).map_err(|e| {
1624
+ magnus::Error::new(
1625
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1626
+ format!("invalid value for `name`: {}", e),
1627
+ )
1628
+ })?,
1629
+ None => Default::default(),
1630
+ },
1631
+ value: match kwargs.get(ruby.to_symbol("value")) {
1632
+ Some(v) => String::try_convert(v).map_err(|e| {
1633
+ magnus::Error::new(
1634
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1635
+ format!("invalid value for `value`: {}", e),
1636
+ )
1637
+ })?,
1638
+ None => Default::default(),
1639
+ },
1640
+ domain: match kwargs.get(ruby.to_symbol("domain")).filter(|v| !v.is_nil()) {
1641
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
1642
+ magnus::Error::new(
1643
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1644
+ format!("invalid value for `domain`: {}", e),
1645
+ )
1646
+ })?),
1647
+ None => None,
1648
+ },
1649
+ path: match kwargs.get(ruby.to_symbol("path")).filter(|v| !v.is_nil()) {
1650
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
1651
+ magnus::Error::new(
1652
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1653
+ format!("invalid value for `path`: {}", e),
1654
+ )
1655
+ })?),
1656
+ None => None,
1657
+ },
1252
1658
  })
1253
1659
  }
1254
1660
 
@@ -1364,172 +1770,438 @@ impl CrawlConfig {
1364
1770
  let (kwargs_opt,) = args.optional;
1365
1771
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
1366
1772
  Ok(Self {
1367
- max_depth: kwargs
1368
- .get(ruby.to_symbol("max_depth"))
1369
- .and_then(|v| usize::try_convert(v).ok()),
1370
- max_pages: kwargs
1371
- .get(ruby.to_symbol("max_pages"))
1372
- .and_then(|v| usize::try_convert(v).ok()),
1373
- max_links_per_page: kwargs
1374
- .get(ruby.to_symbol("max_links_per_page"))
1375
- .and_then(|v| usize::try_convert(v).ok()),
1376
- max_concurrent: kwargs
1377
- .get(ruby.to_symbol("max_concurrent"))
1378
- .and_then(|v| usize::try_convert(v).ok()),
1379
- crawl_strategy: kwargs
1380
- .get(ruby.to_symbol("crawl_strategy"))
1381
- .and_then(|v| CrawlStrategyKind::try_convert(v).ok())
1382
- .unwrap_or(CrawlStrategyKind::Bfs),
1383
- content_filter: kwargs
1384
- .get(ruby.to_symbol("content_filter"))
1385
- .and_then(|v| ContentFilterKind::try_convert(v).ok()),
1386
- bm25_query: kwargs
1387
- .get(ruby.to_symbol("bm25_query"))
1388
- .and_then(|v| String::try_convert(v).ok()),
1389
- bm25_threshold: kwargs
1390
- .get(ruby.to_symbol("bm25_threshold"))
1391
- .and_then(|v| f64::try_convert(v).ok()),
1392
- respect_robots_txt: kwargs
1393
- .get(ruby.to_symbol("respect_robots_txt"))
1394
- .and_then(|v| bool::try_convert(v).ok())
1395
- .unwrap_or(false),
1396
- soft_http_errors: kwargs
1397
- .get(ruby.to_symbol("soft_http_errors"))
1398
- .and_then(|v| bool::try_convert(v).ok())
1399
- .unwrap_or(false),
1400
- user_agent: kwargs
1401
- .get(ruby.to_symbol("user_agent"))
1402
- .and_then(|v| String::try_convert(v).ok()),
1403
- stay_on_domain: kwargs
1404
- .get(ruby.to_symbol("stay_on_domain"))
1405
- .and_then(|v| bool::try_convert(v).ok())
1406
- .unwrap_or(false),
1407
- allow_subdomains: kwargs
1408
- .get(ruby.to_symbol("allow_subdomains"))
1409
- .and_then(|v| bool::try_convert(v).ok())
1410
- .unwrap_or(false),
1411
- include_paths: kwargs
1412
- .get(ruby.to_symbol("include_paths"))
1413
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
1414
- .unwrap_or_default(),
1415
- exclude_paths: kwargs
1416
- .get(ruby.to_symbol("exclude_paths"))
1417
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
1418
- .unwrap_or_default(),
1419
- custom_headers: kwargs
1420
- .get(ruby.to_symbol("custom_headers"))
1421
- .and_then(|v| <HashMap<String, String>>::try_convert(v).ok())
1422
- .unwrap_or_default(),
1423
- request_timeout: kwargs
1424
- .get(ruby.to_symbol("request_timeout"))
1425
- .and_then(|v| u64::try_convert(v).ok())
1426
- .unwrap_or(30000),
1427
- rate_limit_ms: kwargs
1428
- .get(ruby.to_symbol("rate_limit_ms"))
1429
- .and_then(|v| u64::try_convert(v).ok()),
1430
- max_redirects: kwargs
1431
- .get(ruby.to_symbol("max_redirects"))
1432
- .and_then(|v| usize::try_convert(v).ok())
1433
- .unwrap_or(10),
1434
- retry_count: kwargs
1435
- .get(ruby.to_symbol("retry_count"))
1436
- .and_then(|v| usize::try_convert(v).ok())
1437
- .unwrap_or(0),
1438
- retry_codes: kwargs
1439
- .get(ruby.to_symbol("retry_codes"))
1440
- .and_then(|v| <Vec<u16>>::try_convert(v).ok())
1441
- .unwrap_or_default(),
1442
- cookies_enabled: kwargs
1443
- .get(ruby.to_symbol("cookies_enabled"))
1444
- .and_then(|v| bool::try_convert(v).ok())
1445
- .unwrap_or(false),
1446
- auth: kwargs
1447
- .get(ruby.to_symbol("auth"))
1448
- .and_then(|v| AuthConfig::try_convert(v).ok()),
1449
- max_body_size: kwargs
1450
- .get(ruby.to_symbol("max_body_size"))
1451
- .and_then(|v| usize::try_convert(v).ok()),
1452
- remove_tags: kwargs
1453
- .get(ruby.to_symbol("remove_tags"))
1454
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
1455
- .unwrap_or_default(),
1456
- content: kwargs
1457
- .get(ruby.to_symbol("content"))
1458
- .and_then(|v| ContentConfig::try_convert(v).ok())
1459
- .unwrap_or_default(),
1460
- map_limit: kwargs
1461
- .get(ruby.to_symbol("map_limit"))
1462
- .and_then(|v| usize::try_convert(v).ok()),
1463
- map_search: kwargs
1464
- .get(ruby.to_symbol("map_search"))
1465
- .and_then(|v| String::try_convert(v).ok()),
1466
- download_assets: kwargs
1467
- .get(ruby.to_symbol("download_assets"))
1468
- .and_then(|v| bool::try_convert(v).ok())
1469
- .unwrap_or(false),
1470
- asset_types: kwargs
1471
- .get(ruby.to_symbol("asset_types"))
1472
- .and_then(|v| <Vec<AssetCategory>>::try_convert(v).ok())
1473
- .unwrap_or_default(),
1474
- max_asset_size: kwargs
1475
- .get(ruby.to_symbol("max_asset_size"))
1476
- .and_then(|v| usize::try_convert(v).ok()),
1477
- browser: kwargs
1478
- .get(ruby.to_symbol("browser"))
1479
- .and_then(|v| BrowserConfig::try_convert(v).ok())
1480
- .unwrap_or_default(),
1481
- proxy: kwargs
1482
- .get(ruby.to_symbol("proxy"))
1483
- .and_then(|v| ProxyConfig::try_convert(v).ok()),
1484
- user_agents: kwargs
1485
- .get(ruby.to_symbol("user_agents"))
1486
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
1487
- .unwrap_or_default(),
1488
- capture_screenshot: kwargs
1489
- .get(ruby.to_symbol("capture_screenshot"))
1490
- .and_then(|v| bool::try_convert(v).ok())
1491
- .unwrap_or(false),
1492
- follow_document_urls: kwargs
1493
- .get(ruby.to_symbol("follow_document_urls"))
1494
- .and_then(|v| bool::try_convert(v).ok())
1495
- .unwrap_or(false),
1496
- document_url_depth: kwargs
1497
- .get(ruby.to_symbol("document_url_depth"))
1498
- .and_then(|v| u32::try_convert(v).ok()),
1499
- download_documents: kwargs
1500
- .get(ruby.to_symbol("download_documents"))
1501
- .and_then(|v| bool::try_convert(v).ok())
1502
- .unwrap_or(true),
1503
- document_max_size: kwargs
1504
- .get(ruby.to_symbol("document_max_size"))
1505
- .and_then(|v| usize::try_convert(v).ok()),
1506
- document_mime_types: kwargs
1507
- .get(ruby.to_symbol("document_mime_types"))
1508
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
1509
- .unwrap_or_default(),
1510
- document_output_dir: kwargs
1773
+ max_depth: match kwargs.get(ruby.to_symbol("max_depth")).filter(|v| !v.is_nil()) {
1774
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
1775
+ magnus::Error::new(
1776
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1777
+ format!("invalid value for `max_depth`: {}", e),
1778
+ )
1779
+ })?),
1780
+ None => None,
1781
+ },
1782
+ max_pages: match kwargs.get(ruby.to_symbol("max_pages")).filter(|v| !v.is_nil()) {
1783
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
1784
+ magnus::Error::new(
1785
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1786
+ format!("invalid value for `max_pages`: {}", e),
1787
+ )
1788
+ })?),
1789
+ None => None,
1790
+ },
1791
+ max_links_per_page: match kwargs.get(ruby.to_symbol("max_links_per_page")).filter(|v| !v.is_nil()) {
1792
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
1793
+ magnus::Error::new(
1794
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1795
+ format!("invalid value for `max_links_per_page`: {}", e),
1796
+ )
1797
+ })?),
1798
+ None => None,
1799
+ },
1800
+ max_concurrent: match kwargs.get(ruby.to_symbol("max_concurrent")).filter(|v| !v.is_nil()) {
1801
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
1802
+ magnus::Error::new(
1803
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1804
+ format!("invalid value for `max_concurrent`: {}", e),
1805
+ )
1806
+ })?),
1807
+ None => None,
1808
+ },
1809
+ crawl_strategy: match kwargs.get(ruby.to_symbol("crawl_strategy")) {
1810
+ Some(v) => CrawlStrategyKind::try_convert(v).map_err(|e| {
1811
+ magnus::Error::new(
1812
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1813
+ format!("invalid value for `crawl_strategy`: {}", e),
1814
+ )
1815
+ })?,
1816
+ None => CrawlStrategyKind::Bfs,
1817
+ },
1818
+ content_filter: match kwargs.get(ruby.to_symbol("content_filter")).filter(|v| !v.is_nil()) {
1819
+ Some(v) => Some(ContentFilterKind::try_convert(v).map_err(|e| {
1820
+ magnus::Error::new(
1821
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1822
+ format!("invalid value for `content_filter`: {}", e),
1823
+ )
1824
+ })?),
1825
+ None => None,
1826
+ },
1827
+ bm25_query: match kwargs.get(ruby.to_symbol("bm25_query")).filter(|v| !v.is_nil()) {
1828
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
1829
+ magnus::Error::new(
1830
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1831
+ format!("invalid value for `bm25_query`: {}", e),
1832
+ )
1833
+ })?),
1834
+ None => None,
1835
+ },
1836
+ bm25_threshold: match kwargs.get(ruby.to_symbol("bm25_threshold")).filter(|v| !v.is_nil()) {
1837
+ Some(v) => Some(f64::try_convert(v).map_err(|e| {
1838
+ magnus::Error::new(
1839
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1840
+ format!("invalid value for `bm25_threshold`: {}", e),
1841
+ )
1842
+ })?),
1843
+ None => None,
1844
+ },
1845
+ respect_robots_txt: match kwargs.get(ruby.to_symbol("respect_robots_txt")) {
1846
+ Some(v) => bool::try_convert(v).map_err(|e| {
1847
+ magnus::Error::new(
1848
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1849
+ format!("invalid value for `respect_robots_txt`: {}", e),
1850
+ )
1851
+ })?,
1852
+ None => false,
1853
+ },
1854
+ soft_http_errors: match kwargs.get(ruby.to_symbol("soft_http_errors")) {
1855
+ Some(v) => bool::try_convert(v).map_err(|e| {
1856
+ magnus::Error::new(
1857
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1858
+ format!("invalid value for `soft_http_errors`: {}", e),
1859
+ )
1860
+ })?,
1861
+ None => false,
1862
+ },
1863
+ user_agent: match kwargs.get(ruby.to_symbol("user_agent")).filter(|v| !v.is_nil()) {
1864
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
1865
+ magnus::Error::new(
1866
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1867
+ format!("invalid value for `user_agent`: {}", e),
1868
+ )
1869
+ })?),
1870
+ None => None,
1871
+ },
1872
+ stay_on_domain: match kwargs.get(ruby.to_symbol("stay_on_domain")) {
1873
+ Some(v) => bool::try_convert(v).map_err(|e| {
1874
+ magnus::Error::new(
1875
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1876
+ format!("invalid value for `stay_on_domain`: {}", e),
1877
+ )
1878
+ })?,
1879
+ None => false,
1880
+ },
1881
+ allow_subdomains: match kwargs.get(ruby.to_symbol("allow_subdomains")) {
1882
+ Some(v) => bool::try_convert(v).map_err(|e| {
1883
+ magnus::Error::new(
1884
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1885
+ format!("invalid value for `allow_subdomains`: {}", e),
1886
+ )
1887
+ })?,
1888
+ None => false,
1889
+ },
1890
+ include_paths: match kwargs.get(ruby.to_symbol("include_paths")) {
1891
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
1892
+ magnus::Error::new(
1893
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1894
+ format!("invalid value for `include_paths`: {}", e),
1895
+ )
1896
+ })?,
1897
+ None => Default::default(),
1898
+ },
1899
+ exclude_paths: match kwargs.get(ruby.to_symbol("exclude_paths")) {
1900
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
1901
+ magnus::Error::new(
1902
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1903
+ format!("invalid value for `exclude_paths`: {}", e),
1904
+ )
1905
+ })?,
1906
+ None => Default::default(),
1907
+ },
1908
+ custom_headers: match kwargs.get(ruby.to_symbol("custom_headers")) {
1909
+ Some(v) => <HashMap<String, String>>::try_convert(v).map_err(|e| {
1910
+ magnus::Error::new(
1911
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1912
+ format!("invalid value for `custom_headers`: {}", e),
1913
+ )
1914
+ })?,
1915
+ None => Default::default(),
1916
+ },
1917
+ request_timeout: match kwargs.get(ruby.to_symbol("request_timeout")) {
1918
+ Some(v) => u64::try_convert(v).map_err(|e| {
1919
+ magnus::Error::new(
1920
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1921
+ format!("invalid value for `request_timeout`: {}", e),
1922
+ )
1923
+ })?,
1924
+ None => 30000,
1925
+ },
1926
+ rate_limit_ms: match kwargs.get(ruby.to_symbol("rate_limit_ms")).filter(|v| !v.is_nil()) {
1927
+ Some(v) => Some(u64::try_convert(v).map_err(|e| {
1928
+ magnus::Error::new(
1929
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1930
+ format!("invalid value for `rate_limit_ms`: {}", e),
1931
+ )
1932
+ })?),
1933
+ None => None,
1934
+ },
1935
+ max_redirects: match kwargs.get(ruby.to_symbol("max_redirects")) {
1936
+ Some(v) => usize::try_convert(v).map_err(|e| {
1937
+ magnus::Error::new(
1938
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1939
+ format!("invalid value for `max_redirects`: {}", e),
1940
+ )
1941
+ })?,
1942
+ None => 10,
1943
+ },
1944
+ retry_count: match kwargs.get(ruby.to_symbol("retry_count")) {
1945
+ Some(v) => usize::try_convert(v).map_err(|e| {
1946
+ magnus::Error::new(
1947
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1948
+ format!("invalid value for `retry_count`: {}", e),
1949
+ )
1950
+ })?,
1951
+ None => 0,
1952
+ },
1953
+ retry_codes: match kwargs.get(ruby.to_symbol("retry_codes")) {
1954
+ Some(v) => <Vec<u16>>::try_convert(v).map_err(|e| {
1955
+ magnus::Error::new(
1956
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1957
+ format!("invalid value for `retry_codes`: {}", e),
1958
+ )
1959
+ })?,
1960
+ None => Default::default(),
1961
+ },
1962
+ cookies_enabled: match kwargs.get(ruby.to_symbol("cookies_enabled")) {
1963
+ Some(v) => bool::try_convert(v).map_err(|e| {
1964
+ magnus::Error::new(
1965
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1966
+ format!("invalid value for `cookies_enabled`: {}", e),
1967
+ )
1968
+ })?,
1969
+ None => false,
1970
+ },
1971
+ auth: match kwargs.get(ruby.to_symbol("auth")).filter(|v| !v.is_nil()) {
1972
+ Some(v) => Some(AuthConfig::try_convert(v).map_err(|e| {
1973
+ magnus::Error::new(
1974
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1975
+ format!("invalid value for `auth`: {}", e),
1976
+ )
1977
+ })?),
1978
+ None => None,
1979
+ },
1980
+ max_body_size: match kwargs.get(ruby.to_symbol("max_body_size")).filter(|v| !v.is_nil()) {
1981
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
1982
+ magnus::Error::new(
1983
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1984
+ format!("invalid value for `max_body_size`: {}", e),
1985
+ )
1986
+ })?),
1987
+ None => None,
1988
+ },
1989
+ remove_tags: match kwargs.get(ruby.to_symbol("remove_tags")) {
1990
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
1991
+ magnus::Error::new(
1992
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1993
+ format!("invalid value for `remove_tags`: {}", e),
1994
+ )
1995
+ })?,
1996
+ None => Default::default(),
1997
+ },
1998
+ content: match kwargs.get(ruby.to_symbol("content")) {
1999
+ Some(v) => ContentConfig::try_convert(v).map_err(|e| {
2000
+ magnus::Error::new(
2001
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2002
+ format!("invalid value for `content`: {}", e),
2003
+ )
2004
+ })?,
2005
+ None => Default::default(),
2006
+ },
2007
+ map_limit: match kwargs.get(ruby.to_symbol("map_limit")).filter(|v| !v.is_nil()) {
2008
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
2009
+ magnus::Error::new(
2010
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2011
+ format!("invalid value for `map_limit`: {}", e),
2012
+ )
2013
+ })?),
2014
+ None => None,
2015
+ },
2016
+ map_search: match kwargs.get(ruby.to_symbol("map_search")).filter(|v| !v.is_nil()) {
2017
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
2018
+ magnus::Error::new(
2019
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2020
+ format!("invalid value for `map_search`: {}", e),
2021
+ )
2022
+ })?),
2023
+ None => None,
2024
+ },
2025
+ download_assets: match kwargs.get(ruby.to_symbol("download_assets")) {
2026
+ Some(v) => bool::try_convert(v).map_err(|e| {
2027
+ magnus::Error::new(
2028
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2029
+ format!("invalid value for `download_assets`: {}", e),
2030
+ )
2031
+ })?,
2032
+ None => false,
2033
+ },
2034
+ asset_types: match kwargs.get(ruby.to_symbol("asset_types")) {
2035
+ Some(v) => <Vec<AssetCategory>>::try_convert(v).map_err(|e| {
2036
+ magnus::Error::new(
2037
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2038
+ format!("invalid value for `asset_types`: {}", e),
2039
+ )
2040
+ })?,
2041
+ None => Default::default(),
2042
+ },
2043
+ max_asset_size: match kwargs.get(ruby.to_symbol("max_asset_size")).filter(|v| !v.is_nil()) {
2044
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
2045
+ magnus::Error::new(
2046
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2047
+ format!("invalid value for `max_asset_size`: {}", e),
2048
+ )
2049
+ })?),
2050
+ None => None,
2051
+ },
2052
+ browser: match kwargs.get(ruby.to_symbol("browser")) {
2053
+ Some(v) => BrowserConfig::try_convert(v).map_err(|e| {
2054
+ magnus::Error::new(
2055
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2056
+ format!("invalid value for `browser`: {}", e),
2057
+ )
2058
+ })?,
2059
+ None => Default::default(),
2060
+ },
2061
+ proxy: match kwargs.get(ruby.to_symbol("proxy")).filter(|v| !v.is_nil()) {
2062
+ Some(v) => Some(ProxyConfig::try_convert(v).map_err(|e| {
2063
+ magnus::Error::new(
2064
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2065
+ format!("invalid value for `proxy`: {}", e),
2066
+ )
2067
+ })?),
2068
+ None => None,
2069
+ },
2070
+ user_agents: match kwargs.get(ruby.to_symbol("user_agents")) {
2071
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
2072
+ magnus::Error::new(
2073
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2074
+ format!("invalid value for `user_agents`: {}", e),
2075
+ )
2076
+ })?,
2077
+ None => Default::default(),
2078
+ },
2079
+ capture_screenshot: match kwargs.get(ruby.to_symbol("capture_screenshot")) {
2080
+ Some(v) => bool::try_convert(v).map_err(|e| {
2081
+ magnus::Error::new(
2082
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2083
+ format!("invalid value for `capture_screenshot`: {}", e),
2084
+ )
2085
+ })?,
2086
+ None => false,
2087
+ },
2088
+ follow_document_urls: match kwargs.get(ruby.to_symbol("follow_document_urls")) {
2089
+ Some(v) => bool::try_convert(v).map_err(|e| {
2090
+ magnus::Error::new(
2091
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2092
+ format!("invalid value for `follow_document_urls`: {}", e),
2093
+ )
2094
+ })?,
2095
+ None => false,
2096
+ },
2097
+ document_url_depth: match kwargs.get(ruby.to_symbol("document_url_depth")).filter(|v| !v.is_nil()) {
2098
+ Some(v) => Some(u32::try_convert(v).map_err(|e| {
2099
+ magnus::Error::new(
2100
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2101
+ format!("invalid value for `document_url_depth`: {}", e),
2102
+ )
2103
+ })?),
2104
+ None => None,
2105
+ },
2106
+ download_documents: match kwargs.get(ruby.to_symbol("download_documents")) {
2107
+ Some(v) => bool::try_convert(v).map_err(|e| {
2108
+ magnus::Error::new(
2109
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2110
+ format!("invalid value for `download_documents`: {}", e),
2111
+ )
2112
+ })?,
2113
+ None => true,
2114
+ },
2115
+ document_max_size: match kwargs.get(ruby.to_symbol("document_max_size")).filter(|v| !v.is_nil()) {
2116
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
2117
+ magnus::Error::new(
2118
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2119
+ format!("invalid value for `document_max_size`: {}", e),
2120
+ )
2121
+ })?),
2122
+ None => None,
2123
+ },
2124
+ document_mime_types: match kwargs.get(ruby.to_symbol("document_mime_types")) {
2125
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
2126
+ magnus::Error::new(
2127
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2128
+ format!("invalid value for `document_mime_types`: {}", e),
2129
+ )
2130
+ })?,
2131
+ None => Default::default(),
2132
+ },
2133
+ document_output_dir: match kwargs
1511
2134
  .get(ruby.to_symbol("document_output_dir"))
1512
- .and_then(|v| String::try_convert(v).ok()),
1513
- document_content_encoding: kwargs
2135
+ .filter(|v| !v.is_nil())
2136
+ {
2137
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
2138
+ magnus::Error::new(
2139
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2140
+ format!("invalid value for `document_output_dir`: {}", e),
2141
+ )
2142
+ })?),
2143
+ None => None,
2144
+ },
2145
+ document_content_encoding: match kwargs
1514
2146
  .get(ruby.to_symbol("document_content_encoding"))
1515
- .and_then(|v| DocumentContentEncoding::try_convert(v).ok()),
1516
- warc_output: kwargs
1517
- .get(ruby.to_symbol("warc_output"))
1518
- .and_then(|v| String::try_convert(v).ok()),
1519
- browser_profile: kwargs
1520
- .get(ruby.to_symbol("browser_profile"))
1521
- .and_then(|v| String::try_convert(v).ok()),
1522
- save_browser_profile: kwargs
1523
- .get(ruby.to_symbol("save_browser_profile"))
1524
- .and_then(|v| bool::try_convert(v).ok())
1525
- .unwrap_or(false),
1526
- ssrf: kwargs
1527
- .get(ruby.to_symbol("ssrf"))
1528
- .and_then(|v| SsrfPolicy::try_convert(v).ok())
1529
- .unwrap_or(crawlberg::SsrfPolicy::from_env().into()),
1530
- ssrf_deny_private_explicit: kwargs
2147
+ .filter(|v| !v.is_nil())
2148
+ {
2149
+ Some(v) => Some(DocumentContentEncoding::try_convert(v).map_err(|e| {
2150
+ magnus::Error::new(
2151
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2152
+ format!("invalid value for `document_content_encoding`: {}", e),
2153
+ )
2154
+ })?),
2155
+ None => None,
2156
+ },
2157
+ warc_output: match kwargs.get(ruby.to_symbol("warc_output")).filter(|v| !v.is_nil()) {
2158
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
2159
+ magnus::Error::new(
2160
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2161
+ format!("invalid value for `warc_output`: {}", e),
2162
+ )
2163
+ })?),
2164
+ None => None,
2165
+ },
2166
+ browser_profile: match kwargs.get(ruby.to_symbol("browser_profile")).filter(|v| !v.is_nil()) {
2167
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
2168
+ magnus::Error::new(
2169
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2170
+ format!("invalid value for `browser_profile`: {}", e),
2171
+ )
2172
+ })?),
2173
+ None => None,
2174
+ },
2175
+ save_browser_profile: match kwargs.get(ruby.to_symbol("save_browser_profile")) {
2176
+ Some(v) => bool::try_convert(v).map_err(|e| {
2177
+ magnus::Error::new(
2178
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2179
+ format!("invalid value for `save_browser_profile`: {}", e),
2180
+ )
2181
+ })?,
2182
+ None => false,
2183
+ },
2184
+ ssrf: match kwargs.get(ruby.to_symbol("ssrf")) {
2185
+ Some(v) => SsrfPolicy::try_convert(v).map_err(|e| {
2186
+ magnus::Error::new(
2187
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2188
+ format!("invalid value for `ssrf`: {}", e),
2189
+ )
2190
+ })?,
2191
+ None => crawlberg::SsrfPolicy::from_env().into(),
2192
+ },
2193
+ ssrf_deny_private_explicit: match kwargs
1531
2194
  .get(ruby.to_symbol("ssrf_deny_private_explicit"))
1532
- .and_then(|v| bool::try_convert(v).ok()),
2195
+ .filter(|v| !v.is_nil())
2196
+ {
2197
+ Some(v) => Some(bool::try_convert(v).map_err(|e| {
2198
+ magnus::Error::new(
2199
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2200
+ format!("invalid value for `ssrf_deny_private_explicit`: {}", e),
2201
+ )
2202
+ })?),
2203
+ None => None,
2204
+ },
1533
2205
  })
1534
2206
  }
1535
2207
 
@@ -1863,12 +2535,22 @@ impl CrawlEngineHandle {
1863
2535
  use magnus::value::ReprValue;
1864
2536
  let inner = self.inner.clone();
1865
2537
  let core_req: crawlberg::CrawlStreamRequest = req.into();
1866
- let runtime = std::sync::Arc::new(tokio::runtime::Runtime::new().map_err(|e| {
1867
- magnus::Error::new(
1868
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
1869
- e.to_string(),
1870
- )
1871
- })?);
2538
+ // 16 MiB: tokio's ~2 MB default worker stack can overflow on a deep extraction
2539
+ // future (a nested archive member, a multi-stage OCR pipeline), and a stack overflow
2540
+ // aborts the process with SIGBUS instead of raising a catchable panic.
2541
+ const STREAM_RUNTIME_STACK_SIZE_BYTES: usize = 16 * 1024 * 1024;
2542
+ let runtime = std::sync::Arc::new(
2543
+ tokio::runtime::Builder::new_multi_thread()
2544
+ .enable_all()
2545
+ .thread_stack_size(STREAM_RUNTIME_STACK_SIZE_BYTES)
2546
+ .build()
2547
+ .map_err(|e| {
2548
+ magnus::Error::new(
2549
+ unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
2550
+ e.to_string(),
2551
+ )
2552
+ })?,
2553
+ );
1872
2554
  let stream = runtime
1873
2555
  .block_on(async { inner.crawl_stream(core_req).await })
1874
2556
  .map_err(|e| {
@@ -1898,12 +2580,22 @@ impl CrawlEngineHandle {
1898
2580
  use magnus::value::ReprValue;
1899
2581
  let inner = self.inner.clone();
1900
2582
  let core_req: crawlberg::BatchCrawlStreamRequest = req.into();
1901
- let runtime = std::sync::Arc::new(tokio::runtime::Runtime::new().map_err(|e| {
1902
- magnus::Error::new(
1903
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
1904
- e.to_string(),
1905
- )
1906
- })?);
2583
+ // 16 MiB: tokio's ~2 MB default worker stack can overflow on a deep extraction
2584
+ // future (a nested archive member, a multi-stage OCR pipeline), and a stack overflow
2585
+ // aborts the process with SIGBUS instead of raising a catchable panic.
2586
+ const STREAM_RUNTIME_STACK_SIZE_BYTES: usize = 16 * 1024 * 1024;
2587
+ let runtime = std::sync::Arc::new(
2588
+ tokio::runtime::Builder::new_multi_thread()
2589
+ .enable_all()
2590
+ .thread_stack_size(STREAM_RUNTIME_STACK_SIZE_BYTES)
2591
+ .build()
2592
+ .map_err(|e| {
2593
+ magnus::Error::new(
2594
+ unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
2595
+ e.to_string(),
2596
+ )
2597
+ })?,
2598
+ );
1907
2599
  let stream = runtime
1908
2600
  .block_on(async { inner.batch_crawl_stream(core_req).await })
1909
2601
  .map_err(|e| {
@@ -1995,85 +2687,198 @@ impl CrawlPageResult {
1995
2687
  let (kwargs_opt,) = args.optional;
1996
2688
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
1997
2689
  Ok(Self {
1998
- url: kwargs
1999
- .get(ruby.to_symbol("url"))
2000
- .and_then(|v| String::try_convert(v).ok())
2001
- .unwrap_or_default(),
2002
- normalized_url: kwargs
2003
- .get(ruby.to_symbol("normalized_url"))
2004
- .and_then(|v| String::try_convert(v).ok())
2005
- .unwrap_or_default(),
2006
- status_code: kwargs
2007
- .get(ruby.to_symbol("status_code"))
2008
- .and_then(|v| u16::try_convert(v).ok())
2009
- .unwrap_or_default(),
2010
- content_type: kwargs
2011
- .get(ruby.to_symbol("content_type"))
2012
- .and_then(|v| String::try_convert(v).ok())
2013
- .unwrap_or_default(),
2014
- html: kwargs
2015
- .get(ruby.to_symbol("html"))
2016
- .and_then(|v| String::try_convert(v).ok())
2017
- .unwrap_or_default(),
2018
- body_size: kwargs
2019
- .get(ruby.to_symbol("body_size"))
2020
- .and_then(|v| usize::try_convert(v).ok())
2021
- .unwrap_or_default(),
2022
- metadata: kwargs
2023
- .get(ruby.to_symbol("metadata"))
2024
- .and_then(|v| PageMetadata::try_convert(v).ok())
2025
- .unwrap_or_default(),
2026
- links: kwargs
2027
- .get(ruby.to_symbol("links"))
2028
- .and_then(|v| <Vec<LinkInfo>>::try_convert(v).ok())
2029
- .unwrap_or_default(),
2030
- images: kwargs
2031
- .get(ruby.to_symbol("images"))
2032
- .and_then(|v| <Vec<ImageInfo>>::try_convert(v).ok())
2033
- .unwrap_or_default(),
2034
- feeds: kwargs
2035
- .get(ruby.to_symbol("feeds"))
2036
- .and_then(|v| <Vec<FeedInfo>>::try_convert(v).ok())
2037
- .unwrap_or_default(),
2038
- json_ld: kwargs
2039
- .get(ruby.to_symbol("json_ld"))
2040
- .and_then(|v| <Vec<JsonLdEntry>>::try_convert(v).ok())
2041
- .unwrap_or_default(),
2042
- depth: kwargs
2043
- .get(ruby.to_symbol("depth"))
2044
- .and_then(|v| usize::try_convert(v).ok())
2045
- .unwrap_or_default(),
2046
- stayed_on_domain: kwargs
2047
- .get(ruby.to_symbol("stayed_on_domain"))
2048
- .and_then(|v| bool::try_convert(v).ok())
2049
- .unwrap_or_default(),
2050
- was_skipped: kwargs
2051
- .get(ruby.to_symbol("was_skipped"))
2052
- .and_then(|v| bool::try_convert(v).ok())
2053
- .unwrap_or_default(),
2054
- is_pdf: kwargs
2055
- .get(ruby.to_symbol("is_pdf"))
2056
- .and_then(|v| bool::try_convert(v).ok())
2057
- .unwrap_or_default(),
2058
- detected_charset: kwargs
2059
- .get(ruby.to_symbol("detected_charset"))
2060
- .and_then(|v| String::try_convert(v).ok()),
2061
- markdown: kwargs
2062
- .get(ruby.to_symbol("markdown"))
2063
- .and_then(|v| MarkdownResult::try_convert(v).ok()),
2064
- extracted_data: kwargs
2065
- .get(ruby.to_symbol("extracted_data"))
2066
- .and_then(|v| String::try_convert(v).ok()),
2067
- extraction_meta: kwargs
2068
- .get(ruby.to_symbol("extraction_meta"))
2069
- .and_then(|v| ExtractionMeta::try_convert(v).ok()),
2070
- downloaded_document: kwargs
2690
+ url: match kwargs.get(ruby.to_symbol("url")) {
2691
+ Some(v) => String::try_convert(v).map_err(|e| {
2692
+ magnus::Error::new(
2693
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2694
+ format!("invalid value for `url`: {}", e),
2695
+ )
2696
+ })?,
2697
+ None => Default::default(),
2698
+ },
2699
+ normalized_url: match kwargs.get(ruby.to_symbol("normalized_url")) {
2700
+ Some(v) => String::try_convert(v).map_err(|e| {
2701
+ magnus::Error::new(
2702
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2703
+ format!("invalid value for `normalized_url`: {}", e),
2704
+ )
2705
+ })?,
2706
+ None => Default::default(),
2707
+ },
2708
+ status_code: match kwargs.get(ruby.to_symbol("status_code")) {
2709
+ Some(v) => u16::try_convert(v).map_err(|e| {
2710
+ magnus::Error::new(
2711
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2712
+ format!("invalid value for `status_code`: {}", e),
2713
+ )
2714
+ })?,
2715
+ None => Default::default(),
2716
+ },
2717
+ content_type: match kwargs.get(ruby.to_symbol("content_type")) {
2718
+ Some(v) => String::try_convert(v).map_err(|e| {
2719
+ magnus::Error::new(
2720
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2721
+ format!("invalid value for `content_type`: {}", e),
2722
+ )
2723
+ })?,
2724
+ None => Default::default(),
2725
+ },
2726
+ html: match kwargs.get(ruby.to_symbol("html")) {
2727
+ Some(v) => String::try_convert(v).map_err(|e| {
2728
+ magnus::Error::new(
2729
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2730
+ format!("invalid value for `html`: {}", e),
2731
+ )
2732
+ })?,
2733
+ None => Default::default(),
2734
+ },
2735
+ body_size: match kwargs.get(ruby.to_symbol("body_size")) {
2736
+ Some(v) => usize::try_convert(v).map_err(|e| {
2737
+ magnus::Error::new(
2738
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2739
+ format!("invalid value for `body_size`: {}", e),
2740
+ )
2741
+ })?,
2742
+ None => Default::default(),
2743
+ },
2744
+ metadata: match kwargs.get(ruby.to_symbol("metadata")) {
2745
+ Some(v) => PageMetadata::try_convert(v).map_err(|e| {
2746
+ magnus::Error::new(
2747
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2748
+ format!("invalid value for `metadata`: {}", e),
2749
+ )
2750
+ })?,
2751
+ None => Default::default(),
2752
+ },
2753
+ links: match kwargs.get(ruby.to_symbol("links")) {
2754
+ Some(v) => <Vec<LinkInfo>>::try_convert(v).map_err(|e| {
2755
+ magnus::Error::new(
2756
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2757
+ format!("invalid value for `links`: {}", e),
2758
+ )
2759
+ })?,
2760
+ None => Default::default(),
2761
+ },
2762
+ images: match kwargs.get(ruby.to_symbol("images")) {
2763
+ Some(v) => <Vec<ImageInfo>>::try_convert(v).map_err(|e| {
2764
+ magnus::Error::new(
2765
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2766
+ format!("invalid value for `images`: {}", e),
2767
+ )
2768
+ })?,
2769
+ None => Default::default(),
2770
+ },
2771
+ feeds: match kwargs.get(ruby.to_symbol("feeds")) {
2772
+ Some(v) => <Vec<FeedInfo>>::try_convert(v).map_err(|e| {
2773
+ magnus::Error::new(
2774
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2775
+ format!("invalid value for `feeds`: {}", e),
2776
+ )
2777
+ })?,
2778
+ None => Default::default(),
2779
+ },
2780
+ json_ld: match kwargs.get(ruby.to_symbol("json_ld")) {
2781
+ Some(v) => <Vec<JsonLdEntry>>::try_convert(v).map_err(|e| {
2782
+ magnus::Error::new(
2783
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2784
+ format!("invalid value for `json_ld`: {}", e),
2785
+ )
2786
+ })?,
2787
+ None => Default::default(),
2788
+ },
2789
+ depth: match kwargs.get(ruby.to_symbol("depth")) {
2790
+ Some(v) => usize::try_convert(v).map_err(|e| {
2791
+ magnus::Error::new(
2792
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2793
+ format!("invalid value for `depth`: {}", e),
2794
+ )
2795
+ })?,
2796
+ None => Default::default(),
2797
+ },
2798
+ stayed_on_domain: match kwargs.get(ruby.to_symbol("stayed_on_domain")) {
2799
+ Some(v) => bool::try_convert(v).map_err(|e| {
2800
+ magnus::Error::new(
2801
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2802
+ format!("invalid value for `stayed_on_domain`: {}", e),
2803
+ )
2804
+ })?,
2805
+ None => Default::default(),
2806
+ },
2807
+ was_skipped: match kwargs.get(ruby.to_symbol("was_skipped")) {
2808
+ Some(v) => bool::try_convert(v).map_err(|e| {
2809
+ magnus::Error::new(
2810
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2811
+ format!("invalid value for `was_skipped`: {}", e),
2812
+ )
2813
+ })?,
2814
+ None => Default::default(),
2815
+ },
2816
+ is_pdf: match kwargs.get(ruby.to_symbol("is_pdf")) {
2817
+ Some(v) => bool::try_convert(v).map_err(|e| {
2818
+ magnus::Error::new(
2819
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2820
+ format!("invalid value for `is_pdf`: {}", e),
2821
+ )
2822
+ })?,
2823
+ None => Default::default(),
2824
+ },
2825
+ detected_charset: match kwargs.get(ruby.to_symbol("detected_charset")).filter(|v| !v.is_nil()) {
2826
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
2827
+ magnus::Error::new(
2828
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2829
+ format!("invalid value for `detected_charset`: {}", e),
2830
+ )
2831
+ })?),
2832
+ None => None,
2833
+ },
2834
+ markdown: match kwargs.get(ruby.to_symbol("markdown")).filter(|v| !v.is_nil()) {
2835
+ Some(v) => Some(MarkdownResult::try_convert(v).map_err(|e| {
2836
+ magnus::Error::new(
2837
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2838
+ format!("invalid value for `markdown`: {}", e),
2839
+ )
2840
+ })?),
2841
+ None => None,
2842
+ },
2843
+ extracted_data: match kwargs.get(ruby.to_symbol("extracted_data")).filter(|v| !v.is_nil()) {
2844
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
2845
+ magnus::Error::new(
2846
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2847
+ format!("invalid value for `extracted_data`: {}", e),
2848
+ )
2849
+ })?),
2850
+ None => None,
2851
+ },
2852
+ extraction_meta: match kwargs.get(ruby.to_symbol("extraction_meta")).filter(|v| !v.is_nil()) {
2853
+ Some(v) => Some(ExtractionMeta::try_convert(v).map_err(|e| {
2854
+ magnus::Error::new(
2855
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2856
+ format!("invalid value for `extraction_meta`: {}", e),
2857
+ )
2858
+ })?),
2859
+ None => None,
2860
+ },
2861
+ downloaded_document: match kwargs
2071
2862
  .get(ruby.to_symbol("downloaded_document"))
2072
- .and_then(|v| DownloadedDocument::try_convert(v).ok()),
2073
- browser_used: kwargs
2074
- .get(ruby.to_symbol("browser_used"))
2075
- .and_then(|v| bool::try_convert(v).ok())
2076
- .unwrap_or_default(),
2863
+ .filter(|v| !v.is_nil())
2864
+ {
2865
+ Some(v) => Some(DownloadedDocument::try_convert(v).map_err(|e| {
2866
+ magnus::Error::new(
2867
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2868
+ format!("invalid value for `downloaded_document`: {}", e),
2869
+ )
2870
+ })?),
2871
+ None => None,
2872
+ },
2873
+ browser_used: match kwargs.get(ruby.to_symbol("browser_used")) {
2874
+ Some(v) => bool::try_convert(v).map_err(|e| {
2875
+ magnus::Error::new(
2876
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2877
+ format!("invalid value for `browser_used`: {}", e),
2878
+ )
2879
+ })?,
2880
+ None => Default::default(),
2881
+ },
2077
2882
  })
2078
2883
  }
2079
2884
 
@@ -2217,37 +3022,78 @@ impl CrawlResult {
2217
3022
  let (kwargs_opt,) = args.optional;
2218
3023
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2219
3024
  Ok(Self {
2220
- pages: kwargs
2221
- .get(ruby.to_symbol("pages"))
2222
- .and_then(|v| <Vec<CrawlPageResult>>::try_convert(v).ok())
2223
- .unwrap_or_default(),
2224
- final_url: kwargs
2225
- .get(ruby.to_symbol("final_url"))
2226
- .and_then(|v| String::try_convert(v).ok())
2227
- .unwrap_or_default(),
2228
- redirect_count: kwargs
2229
- .get(ruby.to_symbol("redirect_count"))
2230
- .and_then(|v| usize::try_convert(v).ok())
2231
- .unwrap_or_default(),
2232
- was_skipped: kwargs
2233
- .get(ruby.to_symbol("was_skipped"))
2234
- .and_then(|v| bool::try_convert(v).ok())
2235
- .unwrap_or_default(),
2236
- error: kwargs
2237
- .get(ruby.to_symbol("error"))
2238
- .and_then(|v| String::try_convert(v).ok()),
2239
- cookies: kwargs
2240
- .get(ruby.to_symbol("cookies"))
2241
- .and_then(|v| <Vec<CookieInfo>>::try_convert(v).ok())
2242
- .unwrap_or_default(),
2243
- stayed_on_domain: kwargs
2244
- .get(ruby.to_symbol("stayed_on_domain"))
2245
- .and_then(|v| bool::try_convert(v).ok())
2246
- .unwrap_or_default(),
2247
- browser_used: kwargs
2248
- .get(ruby.to_symbol("browser_used"))
2249
- .and_then(|v| bool::try_convert(v).ok())
2250
- .unwrap_or_default(),
3025
+ pages: match kwargs.get(ruby.to_symbol("pages")) {
3026
+ Some(v) => <Vec<CrawlPageResult>>::try_convert(v).map_err(|e| {
3027
+ magnus::Error::new(
3028
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3029
+ format!("invalid value for `pages`: {}", e),
3030
+ )
3031
+ })?,
3032
+ None => Default::default(),
3033
+ },
3034
+ final_url: match kwargs.get(ruby.to_symbol("final_url")) {
3035
+ Some(v) => String::try_convert(v).map_err(|e| {
3036
+ magnus::Error::new(
3037
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3038
+ format!("invalid value for `final_url`: {}", e),
3039
+ )
3040
+ })?,
3041
+ None => Default::default(),
3042
+ },
3043
+ redirect_count: match kwargs.get(ruby.to_symbol("redirect_count")) {
3044
+ Some(v) => usize::try_convert(v).map_err(|e| {
3045
+ magnus::Error::new(
3046
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3047
+ format!("invalid value for `redirect_count`: {}", e),
3048
+ )
3049
+ })?,
3050
+ None => Default::default(),
3051
+ },
3052
+ was_skipped: match kwargs.get(ruby.to_symbol("was_skipped")) {
3053
+ Some(v) => bool::try_convert(v).map_err(|e| {
3054
+ magnus::Error::new(
3055
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3056
+ format!("invalid value for `was_skipped`: {}", e),
3057
+ )
3058
+ })?,
3059
+ None => Default::default(),
3060
+ },
3061
+ error: match kwargs.get(ruby.to_symbol("error")).filter(|v| !v.is_nil()) {
3062
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3063
+ magnus::Error::new(
3064
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3065
+ format!("invalid value for `error`: {}", e),
3066
+ )
3067
+ })?),
3068
+ None => None,
3069
+ },
3070
+ cookies: match kwargs.get(ruby.to_symbol("cookies")) {
3071
+ Some(v) => <Vec<CookieInfo>>::try_convert(v).map_err(|e| {
3072
+ magnus::Error::new(
3073
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3074
+ format!("invalid value for `cookies`: {}", e),
3075
+ )
3076
+ })?,
3077
+ None => Default::default(),
3078
+ },
3079
+ stayed_on_domain: match kwargs.get(ruby.to_symbol("stayed_on_domain")) {
3080
+ Some(v) => bool::try_convert(v).map_err(|e| {
3081
+ magnus::Error::new(
3082
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3083
+ format!("invalid value for `stayed_on_domain`: {}", e),
3084
+ )
3085
+ })?,
3086
+ None => Default::default(),
3087
+ },
3088
+ browser_used: match kwargs.get(ruby.to_symbol("browser_used")) {
3089
+ Some(v) => bool::try_convert(v).map_err(|e| {
3090
+ magnus::Error::new(
3091
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3092
+ format!("invalid value for `browser_used`: {}", e),
3093
+ )
3094
+ })?,
3095
+ None => Default::default(),
3096
+ },
2251
3097
  })
2252
3098
  }
2253
3099
 
@@ -2308,6 +3154,7 @@ impl CrawlResult {
2308
3154
  }
2309
3155
  }
2310
3156
 
3157
+ #[cfg(not(target_arch = "wasm32"))]
2311
3158
  #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2312
3159
  #[serde(default)]
2313
3160
  #[magnus::wrap(class = "Crawlberg::CrawlStreamRequest")]
@@ -2315,8 +3162,10 @@ pub struct CrawlStreamRequest {
2315
3162
  url: String,
2316
3163
  }
2317
3164
 
3165
+ #[cfg(not(target_arch = "wasm32"))]
2318
3166
  unsafe impl IntoValueFromNative for CrawlStreamRequest {}
2319
3167
 
3168
+ #[cfg(not(target_arch = "wasm32"))]
2320
3169
  impl magnus::TryConvert for CrawlStreamRequest {
2321
3170
  fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
2322
3171
  if let Ok(r) = <&CrawlStreamRequest as magnus::TryConvert>::try_convert(val) {
@@ -2341,14 +3190,17 @@ impl magnus::TryConvert for CrawlStreamRequest {
2341
3190
  }
2342
3191
  }
2343
3192
 
3193
+ #[cfg(not(target_arch = "wasm32"))]
2344
3194
  unsafe impl TryConvertOwned for CrawlStreamRequest {}
2345
3195
 
3196
+ #[cfg(not(target_arch = "wasm32"))]
2346
3197
  impl Default for CrawlStreamRequest {
2347
3198
  fn default() -> Self {
2348
3199
  crawlberg::CrawlStreamRequest::default().into()
2349
3200
  }
2350
3201
  }
2351
3202
 
3203
+ #[cfg(not(target_arch = "wasm32"))]
2352
3204
  impl CrawlStreamRequest {
2353
3205
  fn new(args: &[magnus::Value]) -> Result<Self, magnus::Error> {
2354
3206
  let ruby = unsafe { magnus::Ruby::get_unchecked() };
@@ -2356,10 +3208,15 @@ impl CrawlStreamRequest {
2356
3208
  let (kwargs_opt,) = args.optional;
2357
3209
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2358
3210
  Ok(Self {
2359
- url: kwargs
2360
- .get(ruby.to_symbol("url"))
2361
- .and_then(|v| String::try_convert(v).ok())
2362
- .unwrap_or_default(),
3211
+ url: match kwargs.get(ruby.to_symbol("url")) {
3212
+ Some(v) => String::try_convert(v).map_err(|e| {
3213
+ magnus::Error::new(
3214
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3215
+ format!("invalid value for `url`: {}", e),
3216
+ )
3217
+ })?,
3218
+ None => Default::default(),
3219
+ },
2363
3220
  })
2364
3221
  }
2365
3222
 
@@ -2421,28 +3278,60 @@ impl DownloadedAsset {
2421
3278
  let (kwargs_opt,) = args.optional;
2422
3279
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2423
3280
  Ok(Self {
2424
- url: kwargs
2425
- .get(ruby.to_symbol("url"))
2426
- .and_then(|v| String::try_convert(v).ok())
2427
- .unwrap_or_default(),
2428
- content_hash: kwargs
2429
- .get(ruby.to_symbol("content_hash"))
2430
- .and_then(|v| String::try_convert(v).ok())
2431
- .unwrap_or_default(),
2432
- mime_type: kwargs
2433
- .get(ruby.to_symbol("mime_type"))
2434
- .and_then(|v| String::try_convert(v).ok()),
2435
- size: kwargs
2436
- .get(ruby.to_symbol("size"))
2437
- .and_then(|v| usize::try_convert(v).ok())
2438
- .unwrap_or_default(),
2439
- asset_category: kwargs
2440
- .get(ruby.to_symbol("asset_category"))
2441
- .and_then(|v| AssetCategory::try_convert(v).ok())
2442
- .unwrap_or(AssetCategory::Image),
2443
- html_tag: kwargs
2444
- .get(ruby.to_symbol("html_tag"))
2445
- .and_then(|v| String::try_convert(v).ok()),
3281
+ url: match kwargs.get(ruby.to_symbol("url")) {
3282
+ Some(v) => String::try_convert(v).map_err(|e| {
3283
+ magnus::Error::new(
3284
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3285
+ format!("invalid value for `url`: {}", e),
3286
+ )
3287
+ })?,
3288
+ None => Default::default(),
3289
+ },
3290
+ content_hash: match kwargs.get(ruby.to_symbol("content_hash")) {
3291
+ Some(v) => String::try_convert(v).map_err(|e| {
3292
+ magnus::Error::new(
3293
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3294
+ format!("invalid value for `content_hash`: {}", e),
3295
+ )
3296
+ })?,
3297
+ None => Default::default(),
3298
+ },
3299
+ mime_type: match kwargs.get(ruby.to_symbol("mime_type")).filter(|v| !v.is_nil()) {
3300
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3301
+ magnus::Error::new(
3302
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3303
+ format!("invalid value for `mime_type`: {}", e),
3304
+ )
3305
+ })?),
3306
+ None => None,
3307
+ },
3308
+ size: match kwargs.get(ruby.to_symbol("size")) {
3309
+ Some(v) => usize::try_convert(v).map_err(|e| {
3310
+ magnus::Error::new(
3311
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3312
+ format!("invalid value for `size`: {}", e),
3313
+ )
3314
+ })?,
3315
+ None => Default::default(),
3316
+ },
3317
+ asset_category: match kwargs.get(ruby.to_symbol("asset_category")) {
3318
+ Some(v) => AssetCategory::try_convert(v).map_err(|e| {
3319
+ magnus::Error::new(
3320
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3321
+ format!("invalid value for `asset_category`: {}", e),
3322
+ )
3323
+ })?,
3324
+ None => AssetCategory::Image,
3325
+ },
3326
+ html_tag: match kwargs.get(ruby.to_symbol("html_tag")).filter(|v| !v.is_nil()) {
3327
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3328
+ magnus::Error::new(
3329
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3330
+ format!("invalid value for `html_tag`: {}", e),
3331
+ )
3332
+ })?),
3333
+ None => None,
3334
+ },
2446
3335
  })
2447
3336
  }
2448
3337
 
@@ -2471,7 +3360,7 @@ impl DownloadedAsset {
2471
3360
  }
2472
3361
  }
2473
3362
 
2474
- #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
3363
+ #[derive(Clone, Debug, serde::Serialize)]
2475
3364
  #[serde(default)]
2476
3365
  #[magnus::wrap(class = "Crawlberg::DownloadedDocument")]
2477
3366
  pub struct DownloadedDocument {
@@ -2513,6 +3402,14 @@ impl magnus::TryConvert for DownloadedDocument {
2513
3402
  }
2514
3403
 
2515
3404
  unsafe impl TryConvertOwned for DownloadedDocument {}
3405
+ impl<'de> serde::Deserialize<'de> for DownloadedDocument {
3406
+ fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
3407
+ where
3408
+ D: serde::Deserializer<'de>,
3409
+ {
3410
+ <crawlberg::DownloadedDocument as serde::Deserialize>::deserialize(deserializer).map(Into::into)
3411
+ }
3412
+ }
2516
3413
 
2517
3414
  impl Default for DownloadedDocument {
2518
3415
  fn default() -> Self {
@@ -2527,39 +3424,87 @@ impl DownloadedDocument {
2527
3424
  let (kwargs_opt,) = args.optional;
2528
3425
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2529
3426
  Ok(Self {
2530
- url: kwargs
2531
- .get(ruby.to_symbol("url"))
2532
- .and_then(|v| String::try_convert(v).ok())
2533
- .unwrap_or_default(),
2534
- mime_type: kwargs
2535
- .get(ruby.to_symbol("mime_type"))
2536
- .and_then(|v| String::try_convert(v).ok())
2537
- .unwrap_or_default(),
2538
- size: kwargs
2539
- .get(ruby.to_symbol("size"))
2540
- .and_then(|v| usize::try_convert(v).ok())
2541
- .unwrap_or_default(),
2542
- filename: kwargs
2543
- .get(ruby.to_symbol("filename"))
2544
- .and_then(|v| String::try_convert(v).ok()),
2545
- content_hash: kwargs
2546
- .get(ruby.to_symbol("content_hash"))
2547
- .and_then(|v| String::try_convert(v).ok())
2548
- .unwrap_or_default(),
2549
- headers: kwargs
2550
- .get(ruby.to_symbol("headers"))
2551
- .and_then(|v| <HashMap<String, String>>::try_convert(v).ok())
2552
- .unwrap_or_default(),
2553
- truncated: kwargs
2554
- .get(ruby.to_symbol("truncated"))
2555
- .and_then(|v| bool::try_convert(v).ok())
2556
- .unwrap_or_default(),
2557
- content_path: kwargs
2558
- .get(ruby.to_symbol("content_path"))
2559
- .and_then(|v| String::try_convert(v).ok()),
2560
- content_base64: kwargs
2561
- .get(ruby.to_symbol("content_base64"))
2562
- .and_then(|v| String::try_convert(v).ok()),
3427
+ url: match kwargs.get(ruby.to_symbol("url")) {
3428
+ Some(v) => String::try_convert(v).map_err(|e| {
3429
+ magnus::Error::new(
3430
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3431
+ format!("invalid value for `url`: {}", e),
3432
+ )
3433
+ })?,
3434
+ None => Default::default(),
3435
+ },
3436
+ mime_type: match kwargs.get(ruby.to_symbol("mime_type")) {
3437
+ Some(v) => String::try_convert(v).map_err(|e| {
3438
+ magnus::Error::new(
3439
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3440
+ format!("invalid value for `mime_type`: {}", e),
3441
+ )
3442
+ })?,
3443
+ None => Default::default(),
3444
+ },
3445
+ size: match kwargs.get(ruby.to_symbol("size")) {
3446
+ Some(v) => usize::try_convert(v).map_err(|e| {
3447
+ magnus::Error::new(
3448
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3449
+ format!("invalid value for `size`: {}", e),
3450
+ )
3451
+ })?,
3452
+ None => Default::default(),
3453
+ },
3454
+ filename: match kwargs.get(ruby.to_symbol("filename")).filter(|v| !v.is_nil()) {
3455
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3456
+ magnus::Error::new(
3457
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3458
+ format!("invalid value for `filename`: {}", e),
3459
+ )
3460
+ })?),
3461
+ None => None,
3462
+ },
3463
+ content_hash: match kwargs.get(ruby.to_symbol("content_hash")) {
3464
+ Some(v) => String::try_convert(v).map_err(|e| {
3465
+ magnus::Error::new(
3466
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3467
+ format!("invalid value for `content_hash`: {}", e),
3468
+ )
3469
+ })?,
3470
+ None => Default::default(),
3471
+ },
3472
+ headers: match kwargs.get(ruby.to_symbol("headers")) {
3473
+ Some(v) => <HashMap<String, String>>::try_convert(v).map_err(|e| {
3474
+ magnus::Error::new(
3475
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3476
+ format!("invalid value for `headers`: {}", e),
3477
+ )
3478
+ })?,
3479
+ None => Default::default(),
3480
+ },
3481
+ truncated: match kwargs.get(ruby.to_symbol("truncated")) {
3482
+ Some(v) => bool::try_convert(v).map_err(|e| {
3483
+ magnus::Error::new(
3484
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3485
+ format!("invalid value for `truncated`: {}", e),
3486
+ )
3487
+ })?,
3488
+ None => Default::default(),
3489
+ },
3490
+ content_path: match kwargs.get(ruby.to_symbol("content_path")).filter(|v| !v.is_nil()) {
3491
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3492
+ magnus::Error::new(
3493
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3494
+ format!("invalid value for `content_path`: {}", e),
3495
+ )
3496
+ })?),
3497
+ None => None,
3498
+ },
3499
+ content_base64: match kwargs.get(ruby.to_symbol("content_base64")).filter(|v| !v.is_nil()) {
3500
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3501
+ magnus::Error::new(
3502
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3503
+ format!("invalid value for `content_base64`: {}", e),
3504
+ )
3505
+ })?),
3506
+ None => None,
3507
+ },
2563
3508
  })
2564
3509
  }
2565
3510
 
@@ -2652,22 +3597,51 @@ impl ExtractionMeta {
2652
3597
  let (kwargs_opt,) = args.optional;
2653
3598
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2654
3599
  Ok(Self {
2655
- cost: kwargs
2656
- .get(ruby.to_symbol("cost"))
2657
- .and_then(|v| f64::try_convert(v).ok()),
2658
- prompt_tokens: kwargs
2659
- .get(ruby.to_symbol("prompt_tokens"))
2660
- .and_then(|v| u64::try_convert(v).ok()),
2661
- completion_tokens: kwargs
2662
- .get(ruby.to_symbol("completion_tokens"))
2663
- .and_then(|v| u64::try_convert(v).ok()),
2664
- model: kwargs
2665
- .get(ruby.to_symbol("model"))
2666
- .and_then(|v| String::try_convert(v).ok()),
2667
- chunks_processed: kwargs
2668
- .get(ruby.to_symbol("chunks_processed"))
2669
- .and_then(|v| usize::try_convert(v).ok())
2670
- .unwrap_or_default(),
3600
+ cost: match kwargs.get(ruby.to_symbol("cost")).filter(|v| !v.is_nil()) {
3601
+ Some(v) => Some(f64::try_convert(v).map_err(|e| {
3602
+ magnus::Error::new(
3603
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3604
+ format!("invalid value for `cost`: {}", e),
3605
+ )
3606
+ })?),
3607
+ None => None,
3608
+ },
3609
+ prompt_tokens: match kwargs.get(ruby.to_symbol("prompt_tokens")).filter(|v| !v.is_nil()) {
3610
+ Some(v) => Some(u64::try_convert(v).map_err(|e| {
3611
+ magnus::Error::new(
3612
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3613
+ format!("invalid value for `prompt_tokens`: {}", e),
3614
+ )
3615
+ })?),
3616
+ None => None,
3617
+ },
3618
+ completion_tokens: match kwargs.get(ruby.to_symbol("completion_tokens")).filter(|v| !v.is_nil()) {
3619
+ Some(v) => Some(u64::try_convert(v).map_err(|e| {
3620
+ magnus::Error::new(
3621
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3622
+ format!("invalid value for `completion_tokens`: {}", e),
3623
+ )
3624
+ })?),
3625
+ None => None,
3626
+ },
3627
+ model: match kwargs.get(ruby.to_symbol("model")).filter(|v| !v.is_nil()) {
3628
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3629
+ magnus::Error::new(
3630
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3631
+ format!("invalid value for `model`: {}", e),
3632
+ )
3633
+ })?),
3634
+ None => None,
3635
+ },
3636
+ chunks_processed: match kwargs.get(ruby.to_symbol("chunks_processed")) {
3637
+ Some(v) => usize::try_convert(v).map_err(|e| {
3638
+ magnus::Error::new(
3639
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3640
+ format!("invalid value for `chunks_processed`: {}", e),
3641
+ )
3642
+ })?,
3643
+ None => Default::default(),
3644
+ },
2671
3645
  })
2672
3646
  }
2673
3647
 
@@ -2743,20 +3717,42 @@ impl FaviconInfo {
2743
3717
  let (kwargs_opt,) = args.optional;
2744
3718
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2745
3719
  Ok(Self {
2746
- url: kwargs
2747
- .get(ruby.to_symbol("url"))
2748
- .and_then(|v| String::try_convert(v).ok())
2749
- .unwrap_or_default(),
2750
- rel: kwargs
2751
- .get(ruby.to_symbol("rel"))
2752
- .and_then(|v| String::try_convert(v).ok())
2753
- .unwrap_or_default(),
2754
- sizes: kwargs
2755
- .get(ruby.to_symbol("sizes"))
2756
- .and_then(|v| String::try_convert(v).ok()),
2757
- mime_type: kwargs
2758
- .get(ruby.to_symbol("mime_type"))
2759
- .and_then(|v| String::try_convert(v).ok()),
3720
+ url: match kwargs.get(ruby.to_symbol("url")) {
3721
+ Some(v) => String::try_convert(v).map_err(|e| {
3722
+ magnus::Error::new(
3723
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3724
+ format!("invalid value for `url`: {}", e),
3725
+ )
3726
+ })?,
3727
+ None => Default::default(),
3728
+ },
3729
+ rel: match kwargs.get(ruby.to_symbol("rel")) {
3730
+ Some(v) => String::try_convert(v).map_err(|e| {
3731
+ magnus::Error::new(
3732
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3733
+ format!("invalid value for `rel`: {}", e),
3734
+ )
3735
+ })?,
3736
+ None => Default::default(),
3737
+ },
3738
+ sizes: match kwargs.get(ruby.to_symbol("sizes")).filter(|v| !v.is_nil()) {
3739
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3740
+ magnus::Error::new(
3741
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3742
+ format!("invalid value for `sizes`: {}", e),
3743
+ )
3744
+ })?),
3745
+ None => None,
3746
+ },
3747
+ mime_type: match kwargs.get(ruby.to_symbol("mime_type")).filter(|v| !v.is_nil()) {
3748
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3749
+ magnus::Error::new(
3750
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3751
+ format!("invalid value for `mime_type`: {}", e),
3752
+ )
3753
+ })?),
3754
+ None => None,
3755
+ },
2760
3756
  })
2761
3757
  }
2762
3758
 
@@ -2827,17 +3823,33 @@ impl FeedInfo {
2827
3823
  let (kwargs_opt,) = args.optional;
2828
3824
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2829
3825
  Ok(Self {
2830
- url: kwargs
2831
- .get(ruby.to_symbol("url"))
2832
- .and_then(|v| String::try_convert(v).ok())
2833
- .unwrap_or_default(),
2834
- title: kwargs
2835
- .get(ruby.to_symbol("title"))
2836
- .and_then(|v| String::try_convert(v).ok()),
2837
- feed_type: kwargs
2838
- .get(ruby.to_symbol("feed_type"))
2839
- .and_then(|v| FeedType::try_convert(v).ok())
2840
- .unwrap_or(FeedType::Rss),
3826
+ url: match kwargs.get(ruby.to_symbol("url")) {
3827
+ Some(v) => String::try_convert(v).map_err(|e| {
3828
+ magnus::Error::new(
3829
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3830
+ format!("invalid value for `url`: {}", e),
3831
+ )
3832
+ })?,
3833
+ None => Default::default(),
3834
+ },
3835
+ title: match kwargs.get(ruby.to_symbol("title")).filter(|v| !v.is_nil()) {
3836
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
3837
+ magnus::Error::new(
3838
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3839
+ format!("invalid value for `title`: {}", e),
3840
+ )
3841
+ })?),
3842
+ None => None,
3843
+ },
3844
+ feed_type: match kwargs.get(ruby.to_symbol("feed_type")) {
3845
+ Some(v) => FeedType::try_convert(v).map_err(|e| {
3846
+ magnus::Error::new(
3847
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3848
+ format!("invalid value for `feed_type`: {}", e),
3849
+ )
3850
+ })?,
3851
+ None => FeedType::Rss,
3852
+ },
2841
3853
  })
2842
3854
  }
2843
3855
 
@@ -2903,14 +3915,24 @@ impl HeadingInfo {
2903
3915
  let (kwargs_opt,) = args.optional;
2904
3916
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2905
3917
  Ok(Self {
2906
- level: kwargs
2907
- .get(ruby.to_symbol("level"))
2908
- .and_then(|v| u8::try_convert(v).ok())
2909
- .unwrap_or_default(),
2910
- text: kwargs
2911
- .get(ruby.to_symbol("text"))
2912
- .and_then(|v| String::try_convert(v).ok())
2913
- .unwrap_or_default(),
3918
+ level: match kwargs.get(ruby.to_symbol("level")) {
3919
+ Some(v) => u8::try_convert(v).map_err(|e| {
3920
+ magnus::Error::new(
3921
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3922
+ format!("invalid value for `level`: {}", e),
3923
+ )
3924
+ })?,
3925
+ None => Default::default(),
3926
+ },
3927
+ text: match kwargs.get(ruby.to_symbol("text")) {
3928
+ Some(v) => String::try_convert(v).map_err(|e| {
3929
+ magnus::Error::new(
3930
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
3931
+ format!("invalid value for `text`: {}", e),
3932
+ )
3933
+ })?,
3934
+ None => Default::default(),
3935
+ },
2914
3936
  })
2915
3937
  }
2916
3938
 
@@ -2972,14 +3994,24 @@ impl HreflangEntry {
2972
3994
  let (kwargs_opt,) = args.optional;
2973
3995
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2974
3996
  Ok(Self {
2975
- lang: kwargs
2976
- .get(ruby.to_symbol("lang"))
2977
- .and_then(|v| String::try_convert(v).ok())
2978
- .unwrap_or_default(),
2979
- url: kwargs
2980
- .get(ruby.to_symbol("url"))
2981
- .and_then(|v| String::try_convert(v).ok())
2982
- .unwrap_or_default(),
3997
+ lang: match kwargs.get(ruby.to_symbol("lang")) {
3998
+ Some(v) => String::try_convert(v).map_err(|e| {
3999
+ magnus::Error::new(
4000
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4001
+ format!("invalid value for `lang`: {}", e),
4002
+ )
4003
+ })?,
4004
+ None => Default::default(),
4005
+ },
4006
+ url: match kwargs.get(ruby.to_symbol("url")) {
4007
+ Some(v) => String::try_convert(v).map_err(|e| {
4008
+ magnus::Error::new(
4009
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4010
+ format!("invalid value for `url`: {}", e),
4011
+ )
4012
+ })?,
4013
+ None => Default::default(),
4014
+ },
2983
4015
  })
2984
4016
  }
2985
4017
 
@@ -3044,23 +4076,51 @@ impl ImageInfo {
3044
4076
  let (kwargs_opt,) = args.optional;
3045
4077
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
3046
4078
  Ok(Self {
3047
- url: kwargs
3048
- .get(ruby.to_symbol("url"))
3049
- .and_then(|v| String::try_convert(v).ok())
3050
- .unwrap_or_default(),
3051
- alt: kwargs
3052
- .get(ruby.to_symbol("alt"))
3053
- .and_then(|v| String::try_convert(v).ok()),
3054
- width: kwargs
3055
- .get(ruby.to_symbol("width"))
3056
- .and_then(|v| u32::try_convert(v).ok()),
3057
- height: kwargs
3058
- .get(ruby.to_symbol("height"))
3059
- .and_then(|v| u32::try_convert(v).ok()),
3060
- source: kwargs
3061
- .get(ruby.to_symbol("source"))
3062
- .and_then(|v| ImageSource::try_convert(v).ok())
3063
- .unwrap_or(ImageSource::Img),
4079
+ url: match kwargs.get(ruby.to_symbol("url")) {
4080
+ Some(v) => String::try_convert(v).map_err(|e| {
4081
+ magnus::Error::new(
4082
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4083
+ format!("invalid value for `url`: {}", e),
4084
+ )
4085
+ })?,
4086
+ None => Default::default(),
4087
+ },
4088
+ alt: match kwargs.get(ruby.to_symbol("alt")).filter(|v| !v.is_nil()) {
4089
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4090
+ magnus::Error::new(
4091
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4092
+ format!("invalid value for `alt`: {}", e),
4093
+ )
4094
+ })?),
4095
+ None => None,
4096
+ },
4097
+ width: match kwargs.get(ruby.to_symbol("width")).filter(|v| !v.is_nil()) {
4098
+ Some(v) => Some(u32::try_convert(v).map_err(|e| {
4099
+ magnus::Error::new(
4100
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4101
+ format!("invalid value for `width`: {}", e),
4102
+ )
4103
+ })?),
4104
+ None => None,
4105
+ },
4106
+ height: match kwargs.get(ruby.to_symbol("height")).filter(|v| !v.is_nil()) {
4107
+ Some(v) => Some(u32::try_convert(v).map_err(|e| {
4108
+ magnus::Error::new(
4109
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4110
+ format!("invalid value for `height`: {}", e),
4111
+ )
4112
+ })?),
4113
+ None => None,
4114
+ },
4115
+ source: match kwargs.get(ruby.to_symbol("source")) {
4116
+ Some(v) => ImageSource::try_convert(v).map_err(|e| {
4117
+ magnus::Error::new(
4118
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4119
+ format!("invalid value for `source`: {}", e),
4120
+ )
4121
+ })?,
4122
+ None => ImageSource::Img,
4123
+ },
3064
4124
  })
3065
4125
  }
3066
4126
 
@@ -3136,21 +4196,42 @@ impl InteractionResult {
3136
4196
  let (kwargs_opt,) = args.optional;
3137
4197
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
3138
4198
  Ok(Self {
3139
- action_results: kwargs
3140
- .get(ruby.to_symbol("action_results"))
3141
- .and_then(|v| <Vec<ActionResult>>::try_convert(v).ok())
3142
- .unwrap_or_default(),
3143
- final_html: kwargs
3144
- .get(ruby.to_symbol("final_html"))
3145
- .and_then(|v| String::try_convert(v).ok())
3146
- .unwrap_or_default(),
3147
- final_url: kwargs
3148
- .get(ruby.to_symbol("final_url"))
3149
- .and_then(|v| String::try_convert(v).ok())
3150
- .unwrap_or_default(),
3151
- screenshot_base64: kwargs
3152
- .get(ruby.to_symbol("screenshot_base64"))
3153
- .and_then(|v| String::try_convert(v).ok()),
4199
+ action_results: match kwargs.get(ruby.to_symbol("action_results")) {
4200
+ Some(v) => <Vec<ActionResult>>::try_convert(v).map_err(|e| {
4201
+ magnus::Error::new(
4202
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4203
+ format!("invalid value for `action_results`: {}", e),
4204
+ )
4205
+ })?,
4206
+ None => Default::default(),
4207
+ },
4208
+ final_html: match kwargs.get(ruby.to_symbol("final_html")) {
4209
+ Some(v) => String::try_convert(v).map_err(|e| {
4210
+ magnus::Error::new(
4211
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4212
+ format!("invalid value for `final_html`: {}", e),
4213
+ )
4214
+ })?,
4215
+ None => Default::default(),
4216
+ },
4217
+ final_url: match kwargs.get(ruby.to_symbol("final_url")) {
4218
+ Some(v) => String::try_convert(v).map_err(|e| {
4219
+ magnus::Error::new(
4220
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4221
+ format!("invalid value for `final_url`: {}", e),
4222
+ )
4223
+ })?,
4224
+ None => Default::default(),
4225
+ },
4226
+ screenshot_base64: match kwargs.get(ruby.to_symbol("screenshot_base64")).filter(|v| !v.is_nil()) {
4227
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4228
+ magnus::Error::new(
4229
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4230
+ format!("invalid value for `screenshot_base64`: {}", e),
4231
+ )
4232
+ })?),
4233
+ None => None,
4234
+ },
3154
4235
  })
3155
4236
  }
3156
4237
 
@@ -3221,17 +4302,33 @@ impl JsonLdEntry {
3221
4302
  let (kwargs_opt,) = args.optional;
3222
4303
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
3223
4304
  Ok(Self {
3224
- schema_type: kwargs
3225
- .get(ruby.to_symbol("schema_type"))
3226
- .and_then(|v| String::try_convert(v).ok())
3227
- .unwrap_or_default(),
3228
- name: kwargs
3229
- .get(ruby.to_symbol("name"))
3230
- .and_then(|v| String::try_convert(v).ok()),
3231
- raw: kwargs
3232
- .get(ruby.to_symbol("raw"))
3233
- .and_then(|v| String::try_convert(v).ok())
3234
- .unwrap_or_default(),
4305
+ schema_type: match kwargs.get(ruby.to_symbol("schema_type")) {
4306
+ Some(v) => String::try_convert(v).map_err(|e| {
4307
+ magnus::Error::new(
4308
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4309
+ format!("invalid value for `schema_type`: {}", e),
4310
+ )
4311
+ })?,
4312
+ None => Default::default(),
4313
+ },
4314
+ name: match kwargs.get(ruby.to_symbol("name")).filter(|v| !v.is_nil()) {
4315
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4316
+ magnus::Error::new(
4317
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4318
+ format!("invalid value for `name`: {}", e),
4319
+ )
4320
+ })?),
4321
+ None => None,
4322
+ },
4323
+ raw: match kwargs.get(ruby.to_symbol("raw")) {
4324
+ Some(v) => String::try_convert(v).map_err(|e| {
4325
+ magnus::Error::new(
4326
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4327
+ format!("invalid value for `raw`: {}", e),
4328
+ )
4329
+ })?,
4330
+ None => Default::default(),
4331
+ },
3235
4332
  })
3236
4333
  }
3237
4334
 
@@ -3300,25 +4397,51 @@ impl LinkInfo {
3300
4397
  let (kwargs_opt,) = args.optional;
3301
4398
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
3302
4399
  Ok(Self {
3303
- url: kwargs
3304
- .get(ruby.to_symbol("url"))
3305
- .and_then(|v| String::try_convert(v).ok())
3306
- .unwrap_or_default(),
3307
- text: kwargs
3308
- .get(ruby.to_symbol("text"))
3309
- .and_then(|v| String::try_convert(v).ok())
3310
- .unwrap_or_default(),
3311
- link_type: kwargs
3312
- .get(ruby.to_symbol("link_type"))
3313
- .and_then(|v| LinkType::try_convert(v).ok())
3314
- .unwrap_or(LinkType::Internal),
3315
- rel: kwargs
3316
- .get(ruby.to_symbol("rel"))
3317
- .and_then(|v| String::try_convert(v).ok()),
3318
- nofollow: kwargs
3319
- .get(ruby.to_symbol("nofollow"))
3320
- .and_then(|v| bool::try_convert(v).ok())
3321
- .unwrap_or_default(),
4400
+ url: match kwargs.get(ruby.to_symbol("url")) {
4401
+ Some(v) => String::try_convert(v).map_err(|e| {
4402
+ magnus::Error::new(
4403
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4404
+ format!("invalid value for `url`: {}", e),
4405
+ )
4406
+ })?,
4407
+ None => Default::default(),
4408
+ },
4409
+ text: match kwargs.get(ruby.to_symbol("text")) {
4410
+ Some(v) => String::try_convert(v).map_err(|e| {
4411
+ magnus::Error::new(
4412
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4413
+ format!("invalid value for `text`: {}", e),
4414
+ )
4415
+ })?,
4416
+ None => Default::default(),
4417
+ },
4418
+ link_type: match kwargs.get(ruby.to_symbol("link_type")) {
4419
+ Some(v) => LinkType::try_convert(v).map_err(|e| {
4420
+ magnus::Error::new(
4421
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4422
+ format!("invalid value for `link_type`: {}", e),
4423
+ )
4424
+ })?,
4425
+ None => LinkType::Internal,
4426
+ },
4427
+ rel: match kwargs.get(ruby.to_symbol("rel")).filter(|v| !v.is_nil()) {
4428
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4429
+ magnus::Error::new(
4430
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4431
+ format!("invalid value for `rel`: {}", e),
4432
+ )
4433
+ })?),
4434
+ None => None,
4435
+ },
4436
+ nofollow: match kwargs.get(ruby.to_symbol("nofollow")) {
4437
+ Some(v) => bool::try_convert(v).map_err(|e| {
4438
+ magnus::Error::new(
4439
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4440
+ format!("invalid value for `nofollow`: {}", e),
4441
+ )
4442
+ })?,
4443
+ None => Default::default(),
4444
+ },
3322
4445
  })
3323
4446
  }
3324
4447
 
@@ -3391,10 +4514,15 @@ impl MapResult {
3391
4514
  let (kwargs_opt,) = args.optional;
3392
4515
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
3393
4516
  Ok(Self {
3394
- urls: kwargs
3395
- .get(ruby.to_symbol("urls"))
3396
- .and_then(|v| <Vec<SitemapUrl>>::try_convert(v).ok())
3397
- .unwrap_or_default(),
4517
+ urls: match kwargs.get(ruby.to_symbol("urls")) {
4518
+ Some(v) => <Vec<SitemapUrl>>::try_convert(v).map_err(|e| {
4519
+ magnus::Error::new(
4520
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4521
+ format!("invalid value for `urls`: {}", e),
4522
+ )
4523
+ })?,
4524
+ None => Default::default(),
4525
+ },
3398
4526
  })
3399
4527
  }
3400
4528
 
@@ -3456,28 +4584,60 @@ impl MarkdownResult {
3456
4584
  let (kwargs_opt,) = args.optional;
3457
4585
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
3458
4586
  Ok(Self {
3459
- content: kwargs
3460
- .get(ruby.to_symbol("content"))
3461
- .and_then(|v| String::try_convert(v).ok())
3462
- .unwrap_or_default(),
3463
- document_structure: kwargs
3464
- .get(ruby.to_symbol("document_structure"))
3465
- .and_then(|v| String::try_convert(v).ok()),
3466
- tables: kwargs
3467
- .get(ruby.to_symbol("tables"))
3468
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
3469
- .unwrap_or_default(),
3470
- warnings: kwargs
3471
- .get(ruby.to_symbol("warnings"))
3472
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
3473
- .unwrap_or_default(),
3474
- citations: kwargs
3475
- .get(ruby.to_symbol("citations"))
3476
- .and_then(|v| bool::try_convert(v).ok())
3477
- .unwrap_or_default(),
3478
- fit_content: kwargs
3479
- .get(ruby.to_symbol("fit_content"))
3480
- .and_then(|v| String::try_convert(v).ok()),
4587
+ content: match kwargs.get(ruby.to_symbol("content")) {
4588
+ Some(v) => String::try_convert(v).map_err(|e| {
4589
+ magnus::Error::new(
4590
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4591
+ format!("invalid value for `content`: {}", e),
4592
+ )
4593
+ })?,
4594
+ None => Default::default(),
4595
+ },
4596
+ document_structure: match kwargs.get(ruby.to_symbol("document_structure")).filter(|v| !v.is_nil()) {
4597
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4598
+ magnus::Error::new(
4599
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4600
+ format!("invalid value for `document_structure`: {}", e),
4601
+ )
4602
+ })?),
4603
+ None => None,
4604
+ },
4605
+ tables: match kwargs.get(ruby.to_symbol("tables")) {
4606
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
4607
+ magnus::Error::new(
4608
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4609
+ format!("invalid value for `tables`: {}", e),
4610
+ )
4611
+ })?,
4612
+ None => Default::default(),
4613
+ },
4614
+ warnings: match kwargs.get(ruby.to_symbol("warnings")) {
4615
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
4616
+ magnus::Error::new(
4617
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4618
+ format!("invalid value for `warnings`: {}", e),
4619
+ )
4620
+ })?,
4621
+ None => Default::default(),
4622
+ },
4623
+ citations: match kwargs.get(ruby.to_symbol("citations")) {
4624
+ Some(v) => bool::try_convert(v).map_err(|e| {
4625
+ magnus::Error::new(
4626
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4627
+ format!("invalid value for `citations`: {}", e),
4628
+ )
4629
+ })?,
4630
+ None => Default::default(),
4631
+ },
4632
+ fit_content: match kwargs.get(ruby.to_symbol("fit_content")).filter(|v| !v.is_nil()) {
4633
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4634
+ magnus::Error::new(
4635
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4636
+ format!("invalid value for `fit_content`: {}", e),
4637
+ )
4638
+ })?),
4639
+ None => None,
4640
+ },
3481
4641
  })
3482
4642
  }
3483
4643
 
@@ -3601,135 +4761,399 @@ impl PageMetadata {
3601
4761
  let (kwargs_opt,) = args.optional;
3602
4762
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
3603
4763
  Ok(Self {
3604
- title: kwargs
3605
- .get(ruby.to_symbol("title"))
3606
- .and_then(|v| String::try_convert(v).ok()),
3607
- description: kwargs
3608
- .get(ruby.to_symbol("description"))
3609
- .and_then(|v| String::try_convert(v).ok()),
3610
- canonical_url: kwargs
3611
- .get(ruby.to_symbol("canonical_url"))
3612
- .and_then(|v| String::try_convert(v).ok()),
3613
- keywords: kwargs
3614
- .get(ruby.to_symbol("keywords"))
3615
- .and_then(|v| String::try_convert(v).ok()),
3616
- author: kwargs
3617
- .get(ruby.to_symbol("author"))
3618
- .and_then(|v| String::try_convert(v).ok()),
3619
- viewport: kwargs
3620
- .get(ruby.to_symbol("viewport"))
3621
- .and_then(|v| String::try_convert(v).ok()),
3622
- theme_color: kwargs
3623
- .get(ruby.to_symbol("theme_color"))
3624
- .and_then(|v| String::try_convert(v).ok()),
3625
- generator: kwargs
3626
- .get(ruby.to_symbol("generator"))
3627
- .and_then(|v| String::try_convert(v).ok()),
3628
- robots: kwargs
3629
- .get(ruby.to_symbol("robots"))
3630
- .and_then(|v| String::try_convert(v).ok()),
3631
- html_lang: kwargs
3632
- .get(ruby.to_symbol("html_lang"))
3633
- .and_then(|v| String::try_convert(v).ok()),
3634
- html_dir: kwargs
3635
- .get(ruby.to_symbol("html_dir"))
3636
- .and_then(|v| String::try_convert(v).ok()),
3637
- og_title: kwargs
3638
- .get(ruby.to_symbol("og_title"))
3639
- .and_then(|v| String::try_convert(v).ok()),
3640
- og_type: kwargs
3641
- .get(ruby.to_symbol("og_type"))
3642
- .and_then(|v| String::try_convert(v).ok()),
3643
- og_image: kwargs
3644
- .get(ruby.to_symbol("og_image"))
3645
- .and_then(|v| String::try_convert(v).ok()),
3646
- og_description: kwargs
3647
- .get(ruby.to_symbol("og_description"))
3648
- .and_then(|v| String::try_convert(v).ok()),
3649
- og_url: kwargs
3650
- .get(ruby.to_symbol("og_url"))
3651
- .and_then(|v| String::try_convert(v).ok()),
3652
- og_site_name: kwargs
3653
- .get(ruby.to_symbol("og_site_name"))
3654
- .and_then(|v| String::try_convert(v).ok()),
3655
- og_locale: kwargs
3656
- .get(ruby.to_symbol("og_locale"))
3657
- .and_then(|v| String::try_convert(v).ok()),
3658
- og_video: kwargs
3659
- .get(ruby.to_symbol("og_video"))
3660
- .and_then(|v| String::try_convert(v).ok()),
3661
- og_audio: kwargs
3662
- .get(ruby.to_symbol("og_audio"))
3663
- .and_then(|v| String::try_convert(v).ok()),
3664
- og_locale_alternates: kwargs
4764
+ title: match kwargs.get(ruby.to_symbol("title")).filter(|v| !v.is_nil()) {
4765
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4766
+ magnus::Error::new(
4767
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4768
+ format!("invalid value for `title`: {}", e),
4769
+ )
4770
+ })?),
4771
+ None => None,
4772
+ },
4773
+ description: match kwargs.get(ruby.to_symbol("description")).filter(|v| !v.is_nil()) {
4774
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4775
+ magnus::Error::new(
4776
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4777
+ format!("invalid value for `description`: {}", e),
4778
+ )
4779
+ })?),
4780
+ None => None,
4781
+ },
4782
+ canonical_url: match kwargs.get(ruby.to_symbol("canonical_url")).filter(|v| !v.is_nil()) {
4783
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4784
+ magnus::Error::new(
4785
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4786
+ format!("invalid value for `canonical_url`: {}", e),
4787
+ )
4788
+ })?),
4789
+ None => None,
4790
+ },
4791
+ keywords: match kwargs.get(ruby.to_symbol("keywords")).filter(|v| !v.is_nil()) {
4792
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4793
+ magnus::Error::new(
4794
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4795
+ format!("invalid value for `keywords`: {}", e),
4796
+ )
4797
+ })?),
4798
+ None => None,
4799
+ },
4800
+ author: match kwargs.get(ruby.to_symbol("author")).filter(|v| !v.is_nil()) {
4801
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4802
+ magnus::Error::new(
4803
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4804
+ format!("invalid value for `author`: {}", e),
4805
+ )
4806
+ })?),
4807
+ None => None,
4808
+ },
4809
+ viewport: match kwargs.get(ruby.to_symbol("viewport")).filter(|v| !v.is_nil()) {
4810
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4811
+ magnus::Error::new(
4812
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4813
+ format!("invalid value for `viewport`: {}", e),
4814
+ )
4815
+ })?),
4816
+ None => None,
4817
+ },
4818
+ theme_color: match kwargs.get(ruby.to_symbol("theme_color")).filter(|v| !v.is_nil()) {
4819
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4820
+ magnus::Error::new(
4821
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4822
+ format!("invalid value for `theme_color`: {}", e),
4823
+ )
4824
+ })?),
4825
+ None => None,
4826
+ },
4827
+ generator: match kwargs.get(ruby.to_symbol("generator")).filter(|v| !v.is_nil()) {
4828
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4829
+ magnus::Error::new(
4830
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4831
+ format!("invalid value for `generator`: {}", e),
4832
+ )
4833
+ })?),
4834
+ None => None,
4835
+ },
4836
+ robots: match kwargs.get(ruby.to_symbol("robots")).filter(|v| !v.is_nil()) {
4837
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4838
+ magnus::Error::new(
4839
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4840
+ format!("invalid value for `robots`: {}", e),
4841
+ )
4842
+ })?),
4843
+ None => None,
4844
+ },
4845
+ html_lang: match kwargs.get(ruby.to_symbol("html_lang")).filter(|v| !v.is_nil()) {
4846
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4847
+ magnus::Error::new(
4848
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4849
+ format!("invalid value for `html_lang`: {}", e),
4850
+ )
4851
+ })?),
4852
+ None => None,
4853
+ },
4854
+ html_dir: match kwargs.get(ruby.to_symbol("html_dir")).filter(|v| !v.is_nil()) {
4855
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4856
+ magnus::Error::new(
4857
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4858
+ format!("invalid value for `html_dir`: {}", e),
4859
+ )
4860
+ })?),
4861
+ None => None,
4862
+ },
4863
+ og_title: match kwargs.get(ruby.to_symbol("og_title")).filter(|v| !v.is_nil()) {
4864
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4865
+ magnus::Error::new(
4866
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4867
+ format!("invalid value for `og_title`: {}", e),
4868
+ )
4869
+ })?),
4870
+ None => None,
4871
+ },
4872
+ og_type: match kwargs.get(ruby.to_symbol("og_type")).filter(|v| !v.is_nil()) {
4873
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4874
+ magnus::Error::new(
4875
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4876
+ format!("invalid value for `og_type`: {}", e),
4877
+ )
4878
+ })?),
4879
+ None => None,
4880
+ },
4881
+ og_image: match kwargs.get(ruby.to_symbol("og_image")).filter(|v| !v.is_nil()) {
4882
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4883
+ magnus::Error::new(
4884
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4885
+ format!("invalid value for `og_image`: {}", e),
4886
+ )
4887
+ })?),
4888
+ None => None,
4889
+ },
4890
+ og_description: match kwargs.get(ruby.to_symbol("og_description")).filter(|v| !v.is_nil()) {
4891
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4892
+ magnus::Error::new(
4893
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4894
+ format!("invalid value for `og_description`: {}", e),
4895
+ )
4896
+ })?),
4897
+ None => None,
4898
+ },
4899
+ og_url: match kwargs.get(ruby.to_symbol("og_url")).filter(|v| !v.is_nil()) {
4900
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4901
+ magnus::Error::new(
4902
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4903
+ format!("invalid value for `og_url`: {}", e),
4904
+ )
4905
+ })?),
4906
+ None => None,
4907
+ },
4908
+ og_site_name: match kwargs.get(ruby.to_symbol("og_site_name")).filter(|v| !v.is_nil()) {
4909
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4910
+ magnus::Error::new(
4911
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4912
+ format!("invalid value for `og_site_name`: {}", e),
4913
+ )
4914
+ })?),
4915
+ None => None,
4916
+ },
4917
+ og_locale: match kwargs.get(ruby.to_symbol("og_locale")).filter(|v| !v.is_nil()) {
4918
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4919
+ magnus::Error::new(
4920
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4921
+ format!("invalid value for `og_locale`: {}", e),
4922
+ )
4923
+ })?),
4924
+ None => None,
4925
+ },
4926
+ og_video: match kwargs.get(ruby.to_symbol("og_video")).filter(|v| !v.is_nil()) {
4927
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4928
+ magnus::Error::new(
4929
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4930
+ format!("invalid value for `og_video`: {}", e),
4931
+ )
4932
+ })?),
4933
+ None => None,
4934
+ },
4935
+ og_audio: match kwargs.get(ruby.to_symbol("og_audio")).filter(|v| !v.is_nil()) {
4936
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4937
+ magnus::Error::new(
4938
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4939
+ format!("invalid value for `og_audio`: {}", e),
4940
+ )
4941
+ })?),
4942
+ None => None,
4943
+ },
4944
+ og_locale_alternates: match kwargs
3665
4945
  .get(ruby.to_symbol("og_locale_alternates"))
3666
- .and_then(|v| <Vec<String>>::try_convert(v).ok()),
3667
- twitter_card: kwargs
3668
- .get(ruby.to_symbol("twitter_card"))
3669
- .and_then(|v| String::try_convert(v).ok()),
3670
- twitter_title: kwargs
3671
- .get(ruby.to_symbol("twitter_title"))
3672
- .and_then(|v| String::try_convert(v).ok()),
3673
- twitter_description: kwargs
4946
+ .filter(|v| !v.is_nil())
4947
+ {
4948
+ Some(v) => Some(<Vec<String>>::try_convert(v).map_err(|e| {
4949
+ magnus::Error::new(
4950
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4951
+ format!("invalid value for `og_locale_alternates`: {}", e),
4952
+ )
4953
+ })?),
4954
+ None => None,
4955
+ },
4956
+ twitter_card: match kwargs.get(ruby.to_symbol("twitter_card")).filter(|v| !v.is_nil()) {
4957
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4958
+ magnus::Error::new(
4959
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4960
+ format!("invalid value for `twitter_card`: {}", e),
4961
+ )
4962
+ })?),
4963
+ None => None,
4964
+ },
4965
+ twitter_title: match kwargs.get(ruby.to_symbol("twitter_title")).filter(|v| !v.is_nil()) {
4966
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4967
+ magnus::Error::new(
4968
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4969
+ format!("invalid value for `twitter_title`: {}", e),
4970
+ )
4971
+ })?),
4972
+ None => None,
4973
+ },
4974
+ twitter_description: match kwargs
3674
4975
  .get(ruby.to_symbol("twitter_description"))
3675
- .and_then(|v| String::try_convert(v).ok()),
3676
- twitter_image: kwargs
3677
- .get(ruby.to_symbol("twitter_image"))
3678
- .and_then(|v| String::try_convert(v).ok()),
3679
- twitter_site: kwargs
3680
- .get(ruby.to_symbol("twitter_site"))
3681
- .and_then(|v| String::try_convert(v).ok()),
3682
- twitter_creator: kwargs
3683
- .get(ruby.to_symbol("twitter_creator"))
3684
- .and_then(|v| String::try_convert(v).ok()),
3685
- dc_title: kwargs
3686
- .get(ruby.to_symbol("dc_title"))
3687
- .and_then(|v| String::try_convert(v).ok()),
3688
- dc_creator: kwargs
3689
- .get(ruby.to_symbol("dc_creator"))
3690
- .and_then(|v| String::try_convert(v).ok()),
3691
- dc_subject: kwargs
3692
- .get(ruby.to_symbol("dc_subject"))
3693
- .and_then(|v| String::try_convert(v).ok()),
3694
- dc_description: kwargs
3695
- .get(ruby.to_symbol("dc_description"))
3696
- .and_then(|v| String::try_convert(v).ok()),
3697
- dc_publisher: kwargs
3698
- .get(ruby.to_symbol("dc_publisher"))
3699
- .and_then(|v| String::try_convert(v).ok()),
3700
- dc_date: kwargs
3701
- .get(ruby.to_symbol("dc_date"))
3702
- .and_then(|v| String::try_convert(v).ok()),
3703
- dc_type: kwargs
3704
- .get(ruby.to_symbol("dc_type"))
3705
- .and_then(|v| String::try_convert(v).ok()),
3706
- dc_format: kwargs
3707
- .get(ruby.to_symbol("dc_format"))
3708
- .and_then(|v| String::try_convert(v).ok()),
3709
- dc_identifier: kwargs
3710
- .get(ruby.to_symbol("dc_identifier"))
3711
- .and_then(|v| String::try_convert(v).ok()),
3712
- dc_language: kwargs
3713
- .get(ruby.to_symbol("dc_language"))
3714
- .and_then(|v| String::try_convert(v).ok()),
3715
- dc_rights: kwargs
3716
- .get(ruby.to_symbol("dc_rights"))
3717
- .and_then(|v| String::try_convert(v).ok()),
3718
- article: kwargs
3719
- .get(ruby.to_symbol("article"))
3720
- .and_then(|v| ArticleMetadata::try_convert(v).ok()),
3721
- hreflangs: kwargs
3722
- .get(ruby.to_symbol("hreflangs"))
3723
- .and_then(|v| <Vec<HreflangEntry>>::try_convert(v).ok()),
3724
- favicons: kwargs
3725
- .get(ruby.to_symbol("favicons"))
3726
- .and_then(|v| <Vec<FaviconInfo>>::try_convert(v).ok()),
3727
- headings: kwargs
3728
- .get(ruby.to_symbol("headings"))
3729
- .and_then(|v| <Vec<HeadingInfo>>::try_convert(v).ok()),
3730
- word_count: kwargs
3731
- .get(ruby.to_symbol("word_count"))
3732
- .and_then(|v| usize::try_convert(v).ok()),
4976
+ .filter(|v| !v.is_nil())
4977
+ {
4978
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4979
+ magnus::Error::new(
4980
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4981
+ format!("invalid value for `twitter_description`: {}", e),
4982
+ )
4983
+ })?),
4984
+ None => None,
4985
+ },
4986
+ twitter_image: match kwargs.get(ruby.to_symbol("twitter_image")).filter(|v| !v.is_nil()) {
4987
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4988
+ magnus::Error::new(
4989
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4990
+ format!("invalid value for `twitter_image`: {}", e),
4991
+ )
4992
+ })?),
4993
+ None => None,
4994
+ },
4995
+ twitter_site: match kwargs.get(ruby.to_symbol("twitter_site")).filter(|v| !v.is_nil()) {
4996
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
4997
+ magnus::Error::new(
4998
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
4999
+ format!("invalid value for `twitter_site`: {}", e),
5000
+ )
5001
+ })?),
5002
+ None => None,
5003
+ },
5004
+ twitter_creator: match kwargs.get(ruby.to_symbol("twitter_creator")).filter(|v| !v.is_nil()) {
5005
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5006
+ magnus::Error::new(
5007
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5008
+ format!("invalid value for `twitter_creator`: {}", e),
5009
+ )
5010
+ })?),
5011
+ None => None,
5012
+ },
5013
+ dc_title: match kwargs.get(ruby.to_symbol("dc_title")).filter(|v| !v.is_nil()) {
5014
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5015
+ magnus::Error::new(
5016
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5017
+ format!("invalid value for `dc_title`: {}", e),
5018
+ )
5019
+ })?),
5020
+ None => None,
5021
+ },
5022
+ dc_creator: match kwargs.get(ruby.to_symbol("dc_creator")).filter(|v| !v.is_nil()) {
5023
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5024
+ magnus::Error::new(
5025
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5026
+ format!("invalid value for `dc_creator`: {}", e),
5027
+ )
5028
+ })?),
5029
+ None => None,
5030
+ },
5031
+ dc_subject: match kwargs.get(ruby.to_symbol("dc_subject")).filter(|v| !v.is_nil()) {
5032
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5033
+ magnus::Error::new(
5034
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5035
+ format!("invalid value for `dc_subject`: {}", e),
5036
+ )
5037
+ })?),
5038
+ None => None,
5039
+ },
5040
+ dc_description: match kwargs.get(ruby.to_symbol("dc_description")).filter(|v| !v.is_nil()) {
5041
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5042
+ magnus::Error::new(
5043
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5044
+ format!("invalid value for `dc_description`: {}", e),
5045
+ )
5046
+ })?),
5047
+ None => None,
5048
+ },
5049
+ dc_publisher: match kwargs.get(ruby.to_symbol("dc_publisher")).filter(|v| !v.is_nil()) {
5050
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5051
+ magnus::Error::new(
5052
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5053
+ format!("invalid value for `dc_publisher`: {}", e),
5054
+ )
5055
+ })?),
5056
+ None => None,
5057
+ },
5058
+ dc_date: match kwargs.get(ruby.to_symbol("dc_date")).filter(|v| !v.is_nil()) {
5059
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5060
+ magnus::Error::new(
5061
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5062
+ format!("invalid value for `dc_date`: {}", e),
5063
+ )
5064
+ })?),
5065
+ None => None,
5066
+ },
5067
+ dc_type: match kwargs.get(ruby.to_symbol("dc_type")).filter(|v| !v.is_nil()) {
5068
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5069
+ magnus::Error::new(
5070
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5071
+ format!("invalid value for `dc_type`: {}", e),
5072
+ )
5073
+ })?),
5074
+ None => None,
5075
+ },
5076
+ dc_format: match kwargs.get(ruby.to_symbol("dc_format")).filter(|v| !v.is_nil()) {
5077
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5078
+ magnus::Error::new(
5079
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5080
+ format!("invalid value for `dc_format`: {}", e),
5081
+ )
5082
+ })?),
5083
+ None => None,
5084
+ },
5085
+ dc_identifier: match kwargs.get(ruby.to_symbol("dc_identifier")).filter(|v| !v.is_nil()) {
5086
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5087
+ magnus::Error::new(
5088
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5089
+ format!("invalid value for `dc_identifier`: {}", e),
5090
+ )
5091
+ })?),
5092
+ None => None,
5093
+ },
5094
+ dc_language: match kwargs.get(ruby.to_symbol("dc_language")).filter(|v| !v.is_nil()) {
5095
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5096
+ magnus::Error::new(
5097
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5098
+ format!("invalid value for `dc_language`: {}", e),
5099
+ )
5100
+ })?),
5101
+ None => None,
5102
+ },
5103
+ dc_rights: match kwargs.get(ruby.to_symbol("dc_rights")).filter(|v| !v.is_nil()) {
5104
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5105
+ magnus::Error::new(
5106
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5107
+ format!("invalid value for `dc_rights`: {}", e),
5108
+ )
5109
+ })?),
5110
+ None => None,
5111
+ },
5112
+ article: match kwargs.get(ruby.to_symbol("article")).filter(|v| !v.is_nil()) {
5113
+ Some(v) => Some(ArticleMetadata::try_convert(v).map_err(|e| {
5114
+ magnus::Error::new(
5115
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5116
+ format!("invalid value for `article`: {}", e),
5117
+ )
5118
+ })?),
5119
+ None => None,
5120
+ },
5121
+ hreflangs: match kwargs.get(ruby.to_symbol("hreflangs")).filter(|v| !v.is_nil()) {
5122
+ Some(v) => Some(<Vec<HreflangEntry>>::try_convert(v).map_err(|e| {
5123
+ magnus::Error::new(
5124
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5125
+ format!("invalid value for `hreflangs`: {}", e),
5126
+ )
5127
+ })?),
5128
+ None => None,
5129
+ },
5130
+ favicons: match kwargs.get(ruby.to_symbol("favicons")).filter(|v| !v.is_nil()) {
5131
+ Some(v) => Some(<Vec<FaviconInfo>>::try_convert(v).map_err(|e| {
5132
+ magnus::Error::new(
5133
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5134
+ format!("invalid value for `favicons`: {}", e),
5135
+ )
5136
+ })?),
5137
+ None => None,
5138
+ },
5139
+ headings: match kwargs.get(ruby.to_symbol("headings")).filter(|v| !v.is_nil()) {
5140
+ Some(v) => Some(<Vec<HeadingInfo>>::try_convert(v).map_err(|e| {
5141
+ magnus::Error::new(
5142
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5143
+ format!("invalid value for `headings`: {}", e),
5144
+ )
5145
+ })?),
5146
+ None => None,
5147
+ },
5148
+ word_count: match kwargs.get(ruby.to_symbol("word_count")).filter(|v| !v.is_nil()) {
5149
+ Some(v) => Some(usize::try_convert(v).map_err(|e| {
5150
+ magnus::Error::new(
5151
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5152
+ format!("invalid value for `word_count`: {}", e),
5153
+ )
5154
+ })?),
5155
+ None => None,
5156
+ },
3733
5157
  })
3734
5158
  }
3735
5159
 
@@ -3956,16 +5380,33 @@ impl ProxyConfig {
3956
5380
  let (kwargs_opt,) = args.optional;
3957
5381
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
3958
5382
  Ok(Self {
3959
- url: kwargs
3960
- .get(ruby.to_symbol("url"))
3961
- .and_then(|v| String::try_convert(v).ok())
3962
- .unwrap_or_default(),
3963
- username: kwargs
3964
- .get(ruby.to_symbol("username"))
3965
- .and_then(|v| String::try_convert(v).ok()),
3966
- password: kwargs
3967
- .get(ruby.to_symbol("password"))
3968
- .and_then(|v| String::try_convert(v).ok()),
5383
+ url: match kwargs.get(ruby.to_symbol("url")) {
5384
+ Some(v) => String::try_convert(v).map_err(|e| {
5385
+ magnus::Error::new(
5386
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5387
+ format!("invalid value for `url`: {}", e),
5388
+ )
5389
+ })?,
5390
+ None => Default::default(),
5391
+ },
5392
+ username: match kwargs.get(ruby.to_symbol("username")).filter(|v| !v.is_nil()) {
5393
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5394
+ magnus::Error::new(
5395
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5396
+ format!("invalid value for `username`: {}", e),
5397
+ )
5398
+ })?),
5399
+ None => None,
5400
+ },
5401
+ password: match kwargs.get(ruby.to_symbol("password")).filter(|v| !v.is_nil()) {
5402
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5403
+ magnus::Error::new(
5404
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5405
+ format!("invalid value for `password`: {}", e),
5406
+ )
5407
+ })?),
5408
+ None => None,
5409
+ },
3969
5410
  })
3970
5411
  }
3971
5412
 
@@ -4036,27 +5477,69 @@ impl ResponseMeta {
4036
5477
  let (kwargs_opt,) = args.optional;
4037
5478
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
4038
5479
  Ok(Self {
4039
- etag: kwargs
4040
- .get(ruby.to_symbol("etag"))
4041
- .and_then(|v| String::try_convert(v).ok()),
4042
- last_modified: kwargs
4043
- .get(ruby.to_symbol("last_modified"))
4044
- .and_then(|v| String::try_convert(v).ok()),
4045
- cache_control: kwargs
4046
- .get(ruby.to_symbol("cache_control"))
4047
- .and_then(|v| String::try_convert(v).ok()),
4048
- server: kwargs
4049
- .get(ruby.to_symbol("server"))
4050
- .and_then(|v| String::try_convert(v).ok()),
4051
- x_powered_by: kwargs
4052
- .get(ruby.to_symbol("x_powered_by"))
4053
- .and_then(|v| String::try_convert(v).ok()),
4054
- content_language: kwargs
4055
- .get(ruby.to_symbol("content_language"))
4056
- .and_then(|v| String::try_convert(v).ok()),
4057
- content_encoding: kwargs
4058
- .get(ruby.to_symbol("content_encoding"))
4059
- .and_then(|v| String::try_convert(v).ok()),
5480
+ etag: match kwargs.get(ruby.to_symbol("etag")).filter(|v| !v.is_nil()) {
5481
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5482
+ magnus::Error::new(
5483
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5484
+ format!("invalid value for `etag`: {}", e),
5485
+ )
5486
+ })?),
5487
+ None => None,
5488
+ },
5489
+ last_modified: match kwargs.get(ruby.to_symbol("last_modified")).filter(|v| !v.is_nil()) {
5490
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5491
+ magnus::Error::new(
5492
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5493
+ format!("invalid value for `last_modified`: {}", e),
5494
+ )
5495
+ })?),
5496
+ None => None,
5497
+ },
5498
+ cache_control: match kwargs.get(ruby.to_symbol("cache_control")).filter(|v| !v.is_nil()) {
5499
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5500
+ magnus::Error::new(
5501
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5502
+ format!("invalid value for `cache_control`: {}", e),
5503
+ )
5504
+ })?),
5505
+ None => None,
5506
+ },
5507
+ server: match kwargs.get(ruby.to_symbol("server")).filter(|v| !v.is_nil()) {
5508
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5509
+ magnus::Error::new(
5510
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5511
+ format!("invalid value for `server`: {}", e),
5512
+ )
5513
+ })?),
5514
+ None => None,
5515
+ },
5516
+ x_powered_by: match kwargs.get(ruby.to_symbol("x_powered_by")).filter(|v| !v.is_nil()) {
5517
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5518
+ magnus::Error::new(
5519
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5520
+ format!("invalid value for `x_powered_by`: {}", e),
5521
+ )
5522
+ })?),
5523
+ None => None,
5524
+ },
5525
+ content_language: match kwargs.get(ruby.to_symbol("content_language")).filter(|v| !v.is_nil()) {
5526
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5527
+ magnus::Error::new(
5528
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5529
+ format!("invalid value for `content_language`: {}", e),
5530
+ )
5531
+ })?),
5532
+ None => None,
5533
+ },
5534
+ content_encoding: match kwargs.get(ruby.to_symbol("content_encoding")).filter(|v| !v.is_nil()) {
5535
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5536
+ magnus::Error::new(
5537
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5538
+ format!("invalid value for `content_encoding`: {}", e),
5539
+ )
5540
+ })?),
5541
+ None => None,
5542
+ },
4060
5543
  })
4061
5544
  }
4062
5545
 
@@ -4165,112 +5648,270 @@ impl ScrapeResult {
4165
5648
  let (kwargs_opt,) = args.optional;
4166
5649
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
4167
5650
  Ok(Self {
4168
- status_code: kwargs
4169
- .get(ruby.to_symbol("status_code"))
4170
- .and_then(|v| u16::try_convert(v).ok())
4171
- .unwrap_or_default(),
4172
- final_url: kwargs
4173
- .get(ruby.to_symbol("final_url"))
4174
- .and_then(|v| String::try_convert(v).ok())
4175
- .unwrap_or_default(),
4176
- content_type: kwargs
4177
- .get(ruby.to_symbol("content_type"))
4178
- .and_then(|v| String::try_convert(v).ok())
4179
- .unwrap_or_default(),
4180
- html: kwargs
4181
- .get(ruby.to_symbol("html"))
4182
- .and_then(|v| String::try_convert(v).ok())
4183
- .unwrap_or_default(),
4184
- body_size: kwargs
4185
- .get(ruby.to_symbol("body_size"))
4186
- .and_then(|v| usize::try_convert(v).ok())
4187
- .unwrap_or_default(),
4188
- metadata: kwargs
4189
- .get(ruby.to_symbol("metadata"))
4190
- .and_then(|v| PageMetadata::try_convert(v).ok())
4191
- .unwrap_or_default(),
4192
- links: kwargs
4193
- .get(ruby.to_symbol("links"))
4194
- .and_then(|v| <Vec<LinkInfo>>::try_convert(v).ok())
4195
- .unwrap_or_default(),
4196
- images: kwargs
4197
- .get(ruby.to_symbol("images"))
4198
- .and_then(|v| <Vec<ImageInfo>>::try_convert(v).ok())
4199
- .unwrap_or_default(),
4200
- feeds: kwargs
4201
- .get(ruby.to_symbol("feeds"))
4202
- .and_then(|v| <Vec<FeedInfo>>::try_convert(v).ok())
4203
- .unwrap_or_default(),
4204
- json_ld: kwargs
4205
- .get(ruby.to_symbol("json_ld"))
4206
- .and_then(|v| <Vec<JsonLdEntry>>::try_convert(v).ok())
4207
- .unwrap_or_default(),
4208
- is_allowed: kwargs
4209
- .get(ruby.to_symbol("is_allowed"))
4210
- .and_then(|v| bool::try_convert(v).ok())
4211
- .unwrap_or_default(),
4212
- crawl_delay: kwargs
4213
- .get(ruby.to_symbol("crawl_delay"))
4214
- .and_then(|v| u64::try_convert(v).ok()),
4215
- noindex_detected: kwargs
4216
- .get(ruby.to_symbol("noindex_detected"))
4217
- .and_then(|v| bool::try_convert(v).ok())
4218
- .unwrap_or_default(),
4219
- nofollow_detected: kwargs
4220
- .get(ruby.to_symbol("nofollow_detected"))
4221
- .and_then(|v| bool::try_convert(v).ok())
4222
- .unwrap_or_default(),
4223
- x_robots_tag: kwargs
4224
- .get(ruby.to_symbol("x_robots_tag"))
4225
- .and_then(|v| String::try_convert(v).ok()),
4226
- is_pdf: kwargs
4227
- .get(ruby.to_symbol("is_pdf"))
4228
- .and_then(|v| bool::try_convert(v).ok())
4229
- .unwrap_or_default(),
4230
- was_skipped: kwargs
4231
- .get(ruby.to_symbol("was_skipped"))
4232
- .and_then(|v| bool::try_convert(v).ok())
4233
- .unwrap_or_default(),
4234
- detected_charset: kwargs
4235
- .get(ruby.to_symbol("detected_charset"))
4236
- .and_then(|v| String::try_convert(v).ok()),
4237
- auth_header_sent: kwargs
4238
- .get(ruby.to_symbol("auth_header_sent"))
4239
- .and_then(|v| bool::try_convert(v).ok())
4240
- .unwrap_or_default(),
4241
- response_meta: kwargs
4242
- .get(ruby.to_symbol("response_meta"))
4243
- .and_then(|v| ResponseMeta::try_convert(v).ok()),
4244
- assets: kwargs
4245
- .get(ruby.to_symbol("assets"))
4246
- .and_then(|v| <Vec<DownloadedAsset>>::try_convert(v).ok())
4247
- .unwrap_or_default(),
4248
- js_render_hint: kwargs
4249
- .get(ruby.to_symbol("js_render_hint"))
4250
- .and_then(|v| bool::try_convert(v).ok())
4251
- .unwrap_or_default(),
4252
- browser_used: kwargs
4253
- .get(ruby.to_symbol("browser_used"))
4254
- .and_then(|v| bool::try_convert(v).ok())
4255
- .unwrap_or_default(),
4256
- markdown: kwargs
4257
- .get(ruby.to_symbol("markdown"))
4258
- .and_then(|v| MarkdownResult::try_convert(v).ok()),
4259
- extracted_data: kwargs
4260
- .get(ruby.to_symbol("extracted_data"))
4261
- .and_then(|v| String::try_convert(v).ok()),
4262
- extraction_meta: kwargs
4263
- .get(ruby.to_symbol("extraction_meta"))
4264
- .and_then(|v| ExtractionMeta::try_convert(v).ok()),
4265
- screenshot_base64: kwargs
4266
- .get(ruby.to_symbol("screenshot_base64"))
4267
- .and_then(|v| String::try_convert(v).ok()),
4268
- downloaded_document: kwargs
5651
+ status_code: match kwargs.get(ruby.to_symbol("status_code")) {
5652
+ Some(v) => u16::try_convert(v).map_err(|e| {
5653
+ magnus::Error::new(
5654
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5655
+ format!("invalid value for `status_code`: {}", e),
5656
+ )
5657
+ })?,
5658
+ None => Default::default(),
5659
+ },
5660
+ final_url: match kwargs.get(ruby.to_symbol("final_url")) {
5661
+ Some(v) => String::try_convert(v).map_err(|e| {
5662
+ magnus::Error::new(
5663
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5664
+ format!("invalid value for `final_url`: {}", e),
5665
+ )
5666
+ })?,
5667
+ None => Default::default(),
5668
+ },
5669
+ content_type: match kwargs.get(ruby.to_symbol("content_type")) {
5670
+ Some(v) => String::try_convert(v).map_err(|e| {
5671
+ magnus::Error::new(
5672
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5673
+ format!("invalid value for `content_type`: {}", e),
5674
+ )
5675
+ })?,
5676
+ None => Default::default(),
5677
+ },
5678
+ html: match kwargs.get(ruby.to_symbol("html")) {
5679
+ Some(v) => String::try_convert(v).map_err(|e| {
5680
+ magnus::Error::new(
5681
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5682
+ format!("invalid value for `html`: {}", e),
5683
+ )
5684
+ })?,
5685
+ None => Default::default(),
5686
+ },
5687
+ body_size: match kwargs.get(ruby.to_symbol("body_size")) {
5688
+ Some(v) => usize::try_convert(v).map_err(|e| {
5689
+ magnus::Error::new(
5690
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5691
+ format!("invalid value for `body_size`: {}", e),
5692
+ )
5693
+ })?,
5694
+ None => Default::default(),
5695
+ },
5696
+ metadata: match kwargs.get(ruby.to_symbol("metadata")) {
5697
+ Some(v) => PageMetadata::try_convert(v).map_err(|e| {
5698
+ magnus::Error::new(
5699
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5700
+ format!("invalid value for `metadata`: {}", e),
5701
+ )
5702
+ })?,
5703
+ None => Default::default(),
5704
+ },
5705
+ links: match kwargs.get(ruby.to_symbol("links")) {
5706
+ Some(v) => <Vec<LinkInfo>>::try_convert(v).map_err(|e| {
5707
+ magnus::Error::new(
5708
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5709
+ format!("invalid value for `links`: {}", e),
5710
+ )
5711
+ })?,
5712
+ None => Default::default(),
5713
+ },
5714
+ images: match kwargs.get(ruby.to_symbol("images")) {
5715
+ Some(v) => <Vec<ImageInfo>>::try_convert(v).map_err(|e| {
5716
+ magnus::Error::new(
5717
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5718
+ format!("invalid value for `images`: {}", e),
5719
+ )
5720
+ })?,
5721
+ None => Default::default(),
5722
+ },
5723
+ feeds: match kwargs.get(ruby.to_symbol("feeds")) {
5724
+ Some(v) => <Vec<FeedInfo>>::try_convert(v).map_err(|e| {
5725
+ magnus::Error::new(
5726
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5727
+ format!("invalid value for `feeds`: {}", e),
5728
+ )
5729
+ })?,
5730
+ None => Default::default(),
5731
+ },
5732
+ json_ld: match kwargs.get(ruby.to_symbol("json_ld")) {
5733
+ Some(v) => <Vec<JsonLdEntry>>::try_convert(v).map_err(|e| {
5734
+ magnus::Error::new(
5735
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5736
+ format!("invalid value for `json_ld`: {}", e),
5737
+ )
5738
+ })?,
5739
+ None => Default::default(),
5740
+ },
5741
+ is_allowed: match kwargs.get(ruby.to_symbol("is_allowed")) {
5742
+ Some(v) => bool::try_convert(v).map_err(|e| {
5743
+ magnus::Error::new(
5744
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5745
+ format!("invalid value for `is_allowed`: {}", e),
5746
+ )
5747
+ })?,
5748
+ None => Default::default(),
5749
+ },
5750
+ crawl_delay: match kwargs.get(ruby.to_symbol("crawl_delay")).filter(|v| !v.is_nil()) {
5751
+ Some(v) => Some(u64::try_convert(v).map_err(|e| {
5752
+ magnus::Error::new(
5753
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5754
+ format!("invalid value for `crawl_delay`: {}", e),
5755
+ )
5756
+ })?),
5757
+ None => None,
5758
+ },
5759
+ noindex_detected: match kwargs.get(ruby.to_symbol("noindex_detected")) {
5760
+ Some(v) => bool::try_convert(v).map_err(|e| {
5761
+ magnus::Error::new(
5762
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5763
+ format!("invalid value for `noindex_detected`: {}", e),
5764
+ )
5765
+ })?,
5766
+ None => Default::default(),
5767
+ },
5768
+ nofollow_detected: match kwargs.get(ruby.to_symbol("nofollow_detected")) {
5769
+ Some(v) => bool::try_convert(v).map_err(|e| {
5770
+ magnus::Error::new(
5771
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5772
+ format!("invalid value for `nofollow_detected`: {}", e),
5773
+ )
5774
+ })?,
5775
+ None => Default::default(),
5776
+ },
5777
+ x_robots_tag: match kwargs.get(ruby.to_symbol("x_robots_tag")).filter(|v| !v.is_nil()) {
5778
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5779
+ magnus::Error::new(
5780
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5781
+ format!("invalid value for `x_robots_tag`: {}", e),
5782
+ )
5783
+ })?),
5784
+ None => None,
5785
+ },
5786
+ is_pdf: match kwargs.get(ruby.to_symbol("is_pdf")) {
5787
+ Some(v) => bool::try_convert(v).map_err(|e| {
5788
+ magnus::Error::new(
5789
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5790
+ format!("invalid value for `is_pdf`: {}", e),
5791
+ )
5792
+ })?,
5793
+ None => Default::default(),
5794
+ },
5795
+ was_skipped: match kwargs.get(ruby.to_symbol("was_skipped")) {
5796
+ Some(v) => bool::try_convert(v).map_err(|e| {
5797
+ magnus::Error::new(
5798
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5799
+ format!("invalid value for `was_skipped`: {}", e),
5800
+ )
5801
+ })?,
5802
+ None => Default::default(),
5803
+ },
5804
+ detected_charset: match kwargs.get(ruby.to_symbol("detected_charset")).filter(|v| !v.is_nil()) {
5805
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5806
+ magnus::Error::new(
5807
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5808
+ format!("invalid value for `detected_charset`: {}", e),
5809
+ )
5810
+ })?),
5811
+ None => None,
5812
+ },
5813
+ auth_header_sent: match kwargs.get(ruby.to_symbol("auth_header_sent")) {
5814
+ Some(v) => bool::try_convert(v).map_err(|e| {
5815
+ magnus::Error::new(
5816
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5817
+ format!("invalid value for `auth_header_sent`: {}", e),
5818
+ )
5819
+ })?,
5820
+ None => Default::default(),
5821
+ },
5822
+ response_meta: match kwargs.get(ruby.to_symbol("response_meta")).filter(|v| !v.is_nil()) {
5823
+ Some(v) => Some(ResponseMeta::try_convert(v).map_err(|e| {
5824
+ magnus::Error::new(
5825
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5826
+ format!("invalid value for `response_meta`: {}", e),
5827
+ )
5828
+ })?),
5829
+ None => None,
5830
+ },
5831
+ assets: match kwargs.get(ruby.to_symbol("assets")) {
5832
+ Some(v) => <Vec<DownloadedAsset>>::try_convert(v).map_err(|e| {
5833
+ magnus::Error::new(
5834
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5835
+ format!("invalid value for `assets`: {}", e),
5836
+ )
5837
+ })?,
5838
+ None => Default::default(),
5839
+ },
5840
+ js_render_hint: match kwargs.get(ruby.to_symbol("js_render_hint")) {
5841
+ Some(v) => bool::try_convert(v).map_err(|e| {
5842
+ magnus::Error::new(
5843
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5844
+ format!("invalid value for `js_render_hint`: {}", e),
5845
+ )
5846
+ })?,
5847
+ None => Default::default(),
5848
+ },
5849
+ browser_used: match kwargs.get(ruby.to_symbol("browser_used")) {
5850
+ Some(v) => bool::try_convert(v).map_err(|e| {
5851
+ magnus::Error::new(
5852
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5853
+ format!("invalid value for `browser_used`: {}", e),
5854
+ )
5855
+ })?,
5856
+ None => Default::default(),
5857
+ },
5858
+ markdown: match kwargs.get(ruby.to_symbol("markdown")).filter(|v| !v.is_nil()) {
5859
+ Some(v) => Some(MarkdownResult::try_convert(v).map_err(|e| {
5860
+ magnus::Error::new(
5861
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5862
+ format!("invalid value for `markdown`: {}", e),
5863
+ )
5864
+ })?),
5865
+ None => None,
5866
+ },
5867
+ extracted_data: match kwargs.get(ruby.to_symbol("extracted_data")).filter(|v| !v.is_nil()) {
5868
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5869
+ magnus::Error::new(
5870
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5871
+ format!("invalid value for `extracted_data`: {}", e),
5872
+ )
5873
+ })?),
5874
+ None => None,
5875
+ },
5876
+ extraction_meta: match kwargs.get(ruby.to_symbol("extraction_meta")).filter(|v| !v.is_nil()) {
5877
+ Some(v) => Some(ExtractionMeta::try_convert(v).map_err(|e| {
5878
+ magnus::Error::new(
5879
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5880
+ format!("invalid value for `extraction_meta`: {}", e),
5881
+ )
5882
+ })?),
5883
+ None => None,
5884
+ },
5885
+ screenshot_base64: match kwargs.get(ruby.to_symbol("screenshot_base64")).filter(|v| !v.is_nil()) {
5886
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
5887
+ magnus::Error::new(
5888
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5889
+ format!("invalid value for `screenshot_base64`: {}", e),
5890
+ )
5891
+ })?),
5892
+ None => None,
5893
+ },
5894
+ downloaded_document: match kwargs
4269
5895
  .get(ruby.to_symbol("downloaded_document"))
4270
- .and_then(|v| DownloadedDocument::try_convert(v).ok()),
4271
- browser: kwargs
4272
- .get(ruby.to_symbol("browser"))
4273
- .and_then(|v| BrowserExtras::try_convert(v).ok()),
5896
+ .filter(|v| !v.is_nil())
5897
+ {
5898
+ Some(v) => Some(DownloadedDocument::try_convert(v).map_err(|e| {
5899
+ magnus::Error::new(
5900
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5901
+ format!("invalid value for `downloaded_document`: {}", e),
5902
+ )
5903
+ })?),
5904
+ None => None,
5905
+ },
5906
+ browser: match kwargs.get(ruby.to_symbol("browser")).filter(|v| !v.is_nil()) {
5907
+ Some(v) => Some(BrowserExtras::try_convert(v).map_err(|e| {
5908
+ magnus::Error::new(
5909
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
5910
+ format!("invalid value for `browser`: {}", e),
5911
+ )
5912
+ })?),
5913
+ None => None,
5914
+ },
4274
5915
  })
4275
5916
  }
4276
5917
 
@@ -4442,19 +6083,42 @@ impl SitemapUrl {
4442
6083
  let (kwargs_opt,) = args.optional;
4443
6084
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
4444
6085
  Ok(Self {
4445
- url: kwargs
4446
- .get(ruby.to_symbol("url"))
4447
- .and_then(|v| String::try_convert(v).ok())
4448
- .unwrap_or_default(),
4449
- lastmod: kwargs
4450
- .get(ruby.to_symbol("lastmod"))
4451
- .and_then(|v| String::try_convert(v).ok()),
4452
- changefreq: kwargs
4453
- .get(ruby.to_symbol("changefreq"))
4454
- .and_then(|v| String::try_convert(v).ok()),
4455
- priority: kwargs
4456
- .get(ruby.to_symbol("priority"))
4457
- .and_then(|v| String::try_convert(v).ok()),
6086
+ url: match kwargs.get(ruby.to_symbol("url")) {
6087
+ Some(v) => String::try_convert(v).map_err(|e| {
6088
+ magnus::Error::new(
6089
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6090
+ format!("invalid value for `url`: {}", e),
6091
+ )
6092
+ })?,
6093
+ None => Default::default(),
6094
+ },
6095
+ lastmod: match kwargs.get(ruby.to_symbol("lastmod")).filter(|v| !v.is_nil()) {
6096
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
6097
+ magnus::Error::new(
6098
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6099
+ format!("invalid value for `lastmod`: {}", e),
6100
+ )
6101
+ })?),
6102
+ None => None,
6103
+ },
6104
+ changefreq: match kwargs.get(ruby.to_symbol("changefreq")).filter(|v| !v.is_nil()) {
6105
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
6106
+ magnus::Error::new(
6107
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6108
+ format!("invalid value for `changefreq`: {}", e),
6109
+ )
6110
+ })?),
6111
+ None => None,
6112
+ },
6113
+ priority: match kwargs.get(ruby.to_symbol("priority")).filter(|v| !v.is_nil()) {
6114
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
6115
+ magnus::Error::new(
6116
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6117
+ format!("invalid value for `priority`: {}", e),
6118
+ )
6119
+ })?),
6120
+ None => None,
6121
+ },
4458
6122
  })
4459
6123
  }
4460
6124
 
@@ -4475,7 +6139,7 @@ impl SitemapUrl {
4475
6139
  }
4476
6140
  }
4477
6141
 
4478
- #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
6142
+ #[derive(Clone, Debug, serde::Serialize)]
4479
6143
  #[serde(default)]
4480
6144
  #[magnus::wrap(class = "Crawlberg::SsrfPolicy")]
4481
6145
  pub struct SsrfPolicy {
@@ -4512,6 +6176,14 @@ impl magnus::TryConvert for SsrfPolicy {
4512
6176
  }
4513
6177
 
4514
6178
  unsafe impl TryConvertOwned for SsrfPolicy {}
6179
+ impl<'de> serde::Deserialize<'de> for SsrfPolicy {
6180
+ fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
6181
+ where
6182
+ D: serde::Deserializer<'de>,
6183
+ {
6184
+ <crawlberg::SsrfPolicy as serde::Deserialize>::deserialize(deserializer).map(Into::into)
6185
+ }
6186
+ }
4515
6187
 
4516
6188
  impl Default for SsrfPolicy {
4517
6189
  fn default() -> Self {
@@ -4526,26 +6198,42 @@ impl SsrfPolicy {
4526
6198
  let (kwargs_opt,) = args.optional;
4527
6199
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
4528
6200
  Ok(Self {
4529
- deny_private: kwargs
4530
- .get(ruby.to_symbol("deny_private"))
4531
- .and_then(|v| bool::try_convert(v).ok())
4532
- .unwrap_or(true),
4533
- allowlist: kwargs
4534
- .get(ruby.to_symbol("allowlist"))
4535
- .and_then(|v| <Vec<HostMatcher>>::try_convert(v).ok())
4536
- .unwrap_or_default(),
4537
- max_redirects: kwargs
4538
- .get(ruby.to_symbol("max_redirects"))
4539
- .and_then(|v| u8::try_convert(v).ok())
4540
- .unwrap_or(5),
4541
- scheme_allowlist: kwargs
4542
- .get(ruby.to_symbol("scheme_allowlist"))
4543
- .and_then(|v| <Vec<String>>::try_convert(v).ok())
4544
- .unwrap_or(
4545
- serde_json::from_str::<crawlberg::SsrfPolicy>(r#"{}"#)
4546
- .expect("alef-generated default JSON for `SsrfPolicy` failed to deserialize")
4547
- .scheme_allowlist,
4548
- ),
6201
+ deny_private: match kwargs.get(ruby.to_symbol("deny_private")) {
6202
+ Some(v) => bool::try_convert(v).map_err(|e| {
6203
+ magnus::Error::new(
6204
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6205
+ format!("invalid value for `deny_private`: {}", e),
6206
+ )
6207
+ })?,
6208
+ None => true,
6209
+ },
6210
+ allowlist: match kwargs.get(ruby.to_symbol("allowlist")) {
6211
+ Some(v) => <Vec<HostMatcher>>::try_convert(v).map_err(|e| {
6212
+ magnus::Error::new(
6213
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6214
+ format!("invalid value for `allowlist`: {}", e),
6215
+ )
6216
+ })?,
6217
+ None => Default::default(),
6218
+ },
6219
+ max_redirects: match kwargs.get(ruby.to_symbol("max_redirects")) {
6220
+ Some(v) => u8::try_convert(v).map_err(|e| {
6221
+ magnus::Error::new(
6222
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6223
+ format!("invalid value for `max_redirects`: {}", e),
6224
+ )
6225
+ })?,
6226
+ None => 5,
6227
+ },
6228
+ scheme_allowlist: match kwargs.get(ruby.to_symbol("scheme_allowlist")) {
6229
+ Some(v) => <Vec<String>>::try_convert(v).map_err(|e| {
6230
+ magnus::Error::new(
6231
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
6232
+ format!("invalid value for `scheme_allowlist`: {}", e),
6233
+ )
6234
+ })?,
6235
+ None => vec!["http".to_string(), "https".to_string()],
6236
+ },
4549
6237
  })
4550
6238
  }
4551
6239
 
@@ -5364,110 +7052,86 @@ unsafe impl IntoValueFromNative for ScrollDirection {}
5364
7052
  unsafe impl TryConvertOwned for ScrollDirection {}
5365
7053
 
5366
7054
  fn batch_crawl(engine: CrawlEngineHandle, urls: Vec<String>) -> Result<BatchCrawlResults, Error> {
5367
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5368
- magnus::Error::new(
5369
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5370
- e.to_string(),
5371
- )
5372
- })?;
5373
- let result = rt
5374
- .block_on(async { crawlberg::batch_crawl(&engine.inner, urls).await })
5375
- .map_err(|e| {
5376
- magnus::Error::new(
5377
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5378
- e.to_string(),
5379
- )
5380
- })?;
7055
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7056
+ let rt = tokio::runtime::Builder::new_current_thread()
7057
+ .enable_all()
7058
+ .build()
7059
+ .map_err(|e| e.to_string())?;
7060
+ rt.block_on(async { crawlberg::batch_crawl(&engine.inner, urls).await })
7061
+ .map_err(|e| e.to_string())
7062
+ });
7063
+ let result = async_result
7064
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5381
7065
  Ok(result.into())
5382
7066
  }
5383
7067
 
5384
7068
  fn batch_crawl_async(engine: CrawlEngineHandle, urls: Vec<String>) -> Result<BatchCrawlResults, Error> {
5385
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5386
- magnus::Error::new(
5387
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5388
- e.to_string(),
5389
- )
5390
- })?;
5391
- let result = rt
5392
- .block_on(async { crawlberg::batch_crawl(&engine.inner, urls).await })
5393
- .map_err(|e| {
5394
- magnus::Error::new(
5395
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5396
- e.to_string(),
5397
- )
5398
- })?;
7069
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7070
+ let rt = tokio::runtime::Builder::new_current_thread()
7071
+ .enable_all()
7072
+ .build()
7073
+ .map_err(|e| e.to_string())?;
7074
+ rt.block_on(async { crawlberg::batch_crawl(&engine.inner, urls).await })
7075
+ .map_err(|e| e.to_string())
7076
+ });
7077
+ let result = async_result
7078
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5399
7079
  Ok(result.into())
5400
7080
  }
5401
7081
 
5402
7082
  fn batch_scrape(engine: CrawlEngineHandle, urls: Vec<String>) -> Result<BatchScrapeResults, Error> {
5403
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5404
- magnus::Error::new(
5405
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5406
- e.to_string(),
5407
- )
5408
- })?;
5409
- let result = rt
5410
- .block_on(async { crawlberg::batch_scrape(&engine.inner, urls).await })
5411
- .map_err(|e| {
5412
- magnus::Error::new(
5413
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5414
- e.to_string(),
5415
- )
5416
- })?;
7083
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7084
+ let rt = tokio::runtime::Builder::new_current_thread()
7085
+ .enable_all()
7086
+ .build()
7087
+ .map_err(|e| e.to_string())?;
7088
+ rt.block_on(async { crawlberg::batch_scrape(&engine.inner, urls).await })
7089
+ .map_err(|e| e.to_string())
7090
+ });
7091
+ let result = async_result
7092
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5417
7093
  Ok(result.into())
5418
7094
  }
5419
7095
 
5420
7096
  fn batch_scrape_async(engine: CrawlEngineHandle, urls: Vec<String>) -> Result<BatchScrapeResults, Error> {
5421
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5422
- magnus::Error::new(
5423
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5424
- e.to_string(),
5425
- )
5426
- })?;
5427
- let result = rt
5428
- .block_on(async { crawlberg::batch_scrape(&engine.inner, urls).await })
5429
- .map_err(|e| {
5430
- magnus::Error::new(
5431
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5432
- e.to_string(),
5433
- )
5434
- })?;
7097
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7098
+ let rt = tokio::runtime::Builder::new_current_thread()
7099
+ .enable_all()
7100
+ .build()
7101
+ .map_err(|e| e.to_string())?;
7102
+ rt.block_on(async { crawlberg::batch_scrape(&engine.inner, urls).await })
7103
+ .map_err(|e| e.to_string())
7104
+ });
7105
+ let result = async_result
7106
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5435
7107
  Ok(result.into())
5436
7108
  }
5437
7109
 
5438
7110
  fn crawl(engine: CrawlEngineHandle, url: String) -> Result<CrawlResult, Error> {
5439
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5440
- magnus::Error::new(
5441
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5442
- e.to_string(),
5443
- )
5444
- })?;
5445
- let result = rt
5446
- .block_on(async { crawlberg::crawl(&engine.inner, &url).await })
5447
- .map_err(|e| {
5448
- magnus::Error::new(
5449
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5450
- e.to_string(),
5451
- )
5452
- })?;
7111
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7112
+ let rt = tokio::runtime::Builder::new_current_thread()
7113
+ .enable_all()
7114
+ .build()
7115
+ .map_err(|e| e.to_string())?;
7116
+ rt.block_on(async { crawlberg::crawl(&engine.inner, &url).await })
7117
+ .map_err(|e| e.to_string())
7118
+ });
7119
+ let result = async_result
7120
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5453
7121
  Ok(result.into())
5454
7122
  }
5455
7123
 
5456
7124
  fn crawl_async(engine: CrawlEngineHandle, url: String) -> Result<CrawlResult, Error> {
5457
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5458
- magnus::Error::new(
5459
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5460
- e.to_string(),
5461
- )
5462
- })?;
5463
- let result = rt
5464
- .block_on(async { crawlberg::crawl(&engine.inner, &url).await })
5465
- .map_err(|e| {
5466
- magnus::Error::new(
5467
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5468
- e.to_string(),
5469
- )
5470
- })?;
7125
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7126
+ let rt = tokio::runtime::Builder::new_current_thread()
7127
+ .enable_all()
7128
+ .build()
7129
+ .map_err(|e| e.to_string())?;
7130
+ rt.block_on(async { crawlberg::crawl(&engine.inner, &url).await })
7131
+ .map_err(|e| e.to_string())
7132
+ });
7133
+ let result = async_result
7134
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5471
7135
  Ok(result.into())
5472
7136
  }
5473
7137
 
@@ -5501,20 +7165,16 @@ fn generate_citations(markdown: String) -> CitationResult {
5501
7165
 
5502
7166
  fn interact(engine: CrawlEngineHandle, url: String, actions: Vec<PageAction>) -> Result<InteractionResult, Error> {
5503
7167
  let actions_core: Vec<crawlberg::PageAction> = actions.into_iter().map(Into::into).collect();
5504
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5505
- magnus::Error::new(
5506
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5507
- e.to_string(),
5508
- )
5509
- })?;
5510
- let result = rt
5511
- .block_on(async { crawlberg::interact(&engine.inner, &url, actions_core).await })
5512
- .map_err(|e| {
5513
- magnus::Error::new(
5514
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5515
- e.to_string(),
5516
- )
5517
- })?;
7168
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7169
+ let rt = tokio::runtime::Builder::new_current_thread()
7170
+ .enable_all()
7171
+ .build()
7172
+ .map_err(|e| e.to_string())?;
7173
+ rt.block_on(async { crawlberg::interact(&engine.inner, &url, actions_core).await })
7174
+ .map_err(|e| e.to_string())
7175
+ });
7176
+ let result = async_result
7177
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5518
7178
  Ok(result.into())
5519
7179
  }
5520
7180
 
@@ -5524,92 +7184,72 @@ fn interact_async(
5524
7184
  actions: Vec<PageAction>,
5525
7185
  ) -> Result<InteractionResult, Error> {
5526
7186
  let actions_core: Vec<crawlberg::PageAction> = actions.into_iter().map(Into::into).collect();
5527
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5528
- magnus::Error::new(
5529
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5530
- e.to_string(),
5531
- )
5532
- })?;
5533
- let result = rt
5534
- .block_on(async { crawlberg::interact(&engine.inner, &url, actions_core).await })
5535
- .map_err(|e| {
5536
- magnus::Error::new(
5537
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5538
- e.to_string(),
5539
- )
5540
- })?;
7187
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7188
+ let rt = tokio::runtime::Builder::new_current_thread()
7189
+ .enable_all()
7190
+ .build()
7191
+ .map_err(|e| e.to_string())?;
7192
+ rt.block_on(async { crawlberg::interact(&engine.inner, &url, actions_core).await })
7193
+ .map_err(|e| e.to_string())
7194
+ });
7195
+ let result = async_result
7196
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5541
7197
  Ok(result.into())
5542
7198
  }
5543
7199
 
5544
7200
  fn map_urls(engine: CrawlEngineHandle, url: String) -> Result<MapResult, Error> {
5545
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5546
- magnus::Error::new(
5547
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5548
- e.to_string(),
5549
- )
5550
- })?;
5551
- let result = rt
5552
- .block_on(async { crawlberg::map_urls(&engine.inner, &url).await })
5553
- .map_err(|e| {
5554
- magnus::Error::new(
5555
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5556
- e.to_string(),
5557
- )
5558
- })?;
7201
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7202
+ let rt = tokio::runtime::Builder::new_current_thread()
7203
+ .enable_all()
7204
+ .build()
7205
+ .map_err(|e| e.to_string())?;
7206
+ rt.block_on(async { crawlberg::map_urls(&engine.inner, &url).await })
7207
+ .map_err(|e| e.to_string())
7208
+ });
7209
+ let result = async_result
7210
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5559
7211
  Ok(result.into())
5560
7212
  }
5561
7213
 
5562
7214
  fn map_urls_async(engine: CrawlEngineHandle, url: String) -> Result<MapResult, Error> {
5563
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5564
- magnus::Error::new(
5565
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5566
- e.to_string(),
5567
- )
5568
- })?;
5569
- let result = rt
5570
- .block_on(async { crawlberg::map_urls(&engine.inner, &url).await })
5571
- .map_err(|e| {
5572
- magnus::Error::new(
5573
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5574
- e.to_string(),
5575
- )
5576
- })?;
7215
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7216
+ let rt = tokio::runtime::Builder::new_current_thread()
7217
+ .enable_all()
7218
+ .build()
7219
+ .map_err(|e| e.to_string())?;
7220
+ rt.block_on(async { crawlberg::map_urls(&engine.inner, &url).await })
7221
+ .map_err(|e| e.to_string())
7222
+ });
7223
+ let result = async_result
7224
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5577
7225
  Ok(result.into())
5578
7226
  }
5579
7227
 
5580
7228
  fn scrape(engine: CrawlEngineHandle, url: String) -> Result<ScrapeResult, Error> {
5581
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5582
- magnus::Error::new(
5583
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5584
- e.to_string(),
5585
- )
5586
- })?;
5587
- let result = rt
5588
- .block_on(async { crawlberg::scrape(&engine.inner, &url).await })
5589
- .map_err(|e| {
5590
- magnus::Error::new(
5591
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5592
- e.to_string(),
5593
- )
5594
- })?;
7229
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7230
+ let rt = tokio::runtime::Builder::new_current_thread()
7231
+ .enable_all()
7232
+ .build()
7233
+ .map_err(|e| e.to_string())?;
7234
+ rt.block_on(async { crawlberg::scrape(&engine.inner, &url).await })
7235
+ .map_err(|e| e.to_string())
7236
+ });
7237
+ let result = async_result
7238
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5595
7239
  Ok(result.into())
5596
7240
  }
5597
7241
 
5598
7242
  fn scrape_async(engine: CrawlEngineHandle, url: String) -> Result<ScrapeResult, Error> {
5599
- let rt = tokio::runtime::Runtime::new().map_err(|e| {
5600
- magnus::Error::new(
5601
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5602
- e.to_string(),
5603
- )
5604
- })?;
5605
- let result = rt
5606
- .block_on(async { crawlberg::scrape(&engine.inner, &url).await })
5607
- .map_err(|e| {
5608
- magnus::Error::new(
5609
- unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
5610
- e.to_string(),
5611
- )
5612
- })?;
7243
+ let async_result = alef_magnus_run_without_gvl(move || -> Result<_, String> {
7244
+ let rt = tokio::runtime::Builder::new_current_thread()
7245
+ .enable_all()
7246
+ .build()
7247
+ .map_err(|e| e.to_string())?;
7248
+ rt.block_on(async { crawlberg::scrape(&engine.inner, &url).await })
7249
+ .map_err(|e| e.to_string())
7250
+ });
7251
+ let result = async_result
7252
+ .map_err(|message| magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_runtime_error(), message))?;
5613
7253
  Ok(result.into())
5614
7254
  }
5615
7255
 
@@ -5726,6 +7366,7 @@ impl From<crawlberg::BatchCrawlResults> for BatchCrawlResults {
5726
7366
  }
5727
7367
  }
5728
7368
 
7369
+ #[cfg(not(target_arch = "wasm32"))]
5729
7370
  #[allow(clippy::needless_update)]
5730
7371
  impl From<BatchCrawlStreamRequest> for crawlberg::BatchCrawlStreamRequest {
5731
7372
  fn from(val: BatchCrawlStreamRequest) -> Self {
@@ -5736,6 +7377,7 @@ impl From<BatchCrawlStreamRequest> for crawlberg::BatchCrawlStreamRequest {
5736
7377
  }
5737
7378
  }
5738
7379
 
7380
+ #[cfg(not(target_arch = "wasm32"))]
5739
7381
  impl From<crawlberg::BatchCrawlStreamRequest> for BatchCrawlStreamRequest {
5740
7382
  fn from(val: crawlberg::BatchCrawlStreamRequest) -> Self {
5741
7383
  Self {
@@ -6185,6 +7827,7 @@ impl From<crawlberg::CrawlResult> for CrawlResult {
6185
7827
  }
6186
7828
  }
6187
7829
 
7830
+ #[cfg(not(target_arch = "wasm32"))]
6188
7831
  #[allow(clippy::needless_update)]
6189
7832
  impl From<CrawlStreamRequest> for crawlberg::CrawlStreamRequest {
6190
7833
  fn from(val: CrawlStreamRequest) -> Self {
@@ -6195,6 +7838,7 @@ impl From<CrawlStreamRequest> for crawlberg::CrawlStreamRequest {
6195
7838
  }
6196
7839
  }
6197
7840
 
7841
+ #[cfg(not(target_arch = "wasm32"))]
6198
7842
  impl From<crawlberg::CrawlStreamRequest> for CrawlStreamRequest {
6199
7843
  fn from(val: crawlberg::CrawlStreamRequest) -> Self {
6200
7844
  Self {
@@ -6970,6 +8614,7 @@ impl From<crawlberg::ContentFilterKind> for ContentFilterKind {
6970
8614
  }
6971
8615
  }
6972
8616
 
8617
+ #[cfg(not(target_arch = "wasm32"))]
6973
8618
  impl From<crawlberg::CrawlEvent> for CrawlEvent {
6974
8619
  fn from(val: crawlberg::CrawlEvent) -> Self {
6975
8620
  match val {
@@ -7424,8 +9069,10 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
7424
9069
 
7425
9070
  let class = module.define_class("BatchCrawlStreamRequest", ruby.class_object())?;
7426
9071
 
9072
+ #[cfg(not(target_arch = "wasm32"))]
7427
9073
  class.define_singleton_method("new", function!(BatchCrawlStreamRequest::new, -1))?;
7428
9074
 
9075
+ #[cfg(not(target_arch = "wasm32"))]
7429
9076
  class.define_method("urls", method!(BatchCrawlStreamRequest::urls, 0))?;
7430
9077
 
7431
9078
  let class = module.define_class("BatchScrapeResult", ruby.class_object())?;
@@ -7740,8 +9387,10 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
7740
9387
 
7741
9388
  let class = module.define_class("CrawlStreamRequest", ruby.class_object())?;
7742
9389
 
9390
+ #[cfg(not(target_arch = "wasm32"))]
7743
9391
  class.define_singleton_method("new", function!(CrawlStreamRequest::new, -1))?;
7744
9392
 
9393
+ #[cfg(not(target_arch = "wasm32"))]
7745
9394
  class.define_method("url", method!(CrawlStreamRequest::url, 0))?;
7746
9395
 
7747
9396
  let class = module.define_class("DownloadedAsset", ruby.class_object())?;