yerba 0.9.2-aarch64-linux-gnu → 0.10.0-aarch64-linux-gnu

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -17
  3. data/exe/aarch64-linux-gnu/yerba +0 -0
  4. data/ext/yerba/include/yerba.h +56 -34
  5. data/ext/yerba/yerba.c +268 -186
  6. data/lib/yerba/3.2/yerba.so +0 -0
  7. data/lib/yerba/3.3/yerba.so +0 -0
  8. data/lib/yerba/3.4/yerba.so +0 -0
  9. data/lib/yerba/4.0/yerba.so +0 -0
  10. data/lib/yerba/collection.rb +4 -4
  11. data/lib/yerba/document.rb +134 -0
  12. data/lib/yerba/formatting.rb +1 -0
  13. data/lib/yerba/location.rb +8 -1
  14. data/lib/yerba/map.rb +16 -6
  15. data/lib/yerba/node.rb +41 -0
  16. data/lib/yerba/query_result.rb +33 -10
  17. data/lib/yerba/scalar.rb +29 -0
  18. data/lib/yerba/selector.rb +3 -1
  19. data/lib/yerba/sequence.rb +38 -33
  20. data/lib/yerba/version.rb +1 -1
  21. data/rust/Cargo.lock +1 -1
  22. data/rust/Cargo.toml +1 -1
  23. data/rust/src/commands/get.rs +12 -12
  24. data/rust/src/commands/init.rs +8 -8
  25. data/rust/src/commands/insert.rs +4 -18
  26. data/rust/src/commands/location.rs +2 -0
  27. data/rust/src/commands/mod.rs +34 -6
  28. data/rust/src/commands/move_item.rs +1 -1
  29. data/rust/src/commands/move_key.rs +8 -8
  30. data/rust/src/commands/rename.rs +1 -1
  31. data/rust/src/commands/selectors.rs +1 -1
  32. data/rust/src/commands/set.rs +14 -6
  33. data/rust/src/document/condition.rs +25 -25
  34. data/rust/src/document/delete.rs +57 -43
  35. data/rust/src/document/get.rs +91 -82
  36. data/rust/src/document/insert.rs +77 -77
  37. data/rust/src/document/mod.rs +138 -64
  38. data/rust/src/document/nodes.rs +162 -0
  39. data/rust/src/document/schema.rs +8 -8
  40. data/rust/src/document/set.rs +49 -26
  41. data/rust/src/document/sort.rs +54 -54
  42. data/rust/src/document/style.rs +50 -49
  43. data/rust/src/document/unique.rs +5 -5
  44. data/rust/src/error.rs +8 -4
  45. data/rust/src/ffi.rs +218 -106
  46. data/rust/src/json.rs +62 -2
  47. data/rust/src/lib.rs +2 -1
  48. data/rust/src/main.rs +2 -1
  49. data/rust/src/selector.rs +48 -7
  50. data/rust/src/syntax.rs +449 -56
  51. data/rust/src/validation.rs +5 -3
  52. data/rust/src/yerbafile.rs +124 -76
  53. metadata +3 -2
data/rust/src/ffi.rs CHANGED
@@ -12,7 +12,7 @@ use std::ffi::{CStr, CString};
12
12
  use std::os::raw::c_char;
13
13
  use std::ptr;
14
14
 
15
- use crate::syntax::{detect_yaml_type, YerbaValueType};
15
+ use crate::syntax::{detect_yaml_type, resolve_plain_scalar, PlainScalar, YerbaValueType};
16
16
  use crate::NodeType;
17
17
  use crate::{Document, InsertPosition, QuoteStyle};
18
18
 
@@ -44,6 +44,30 @@ pub struct YerbaTypedValue {
44
44
  pub value_type: YerbaValueType,
45
45
  }
46
46
 
47
+ impl YerbaTypedValue {
48
+ fn new(text: &str, value_type: YerbaValueType) -> Self {
49
+ YerbaTypedValue {
50
+ text: CString::new(typed_text(text, value_type)).unwrap_or_default().into_raw(),
51
+ value_type,
52
+ }
53
+ }
54
+ }
55
+
56
+ fn typed_text(text: &str, value_type: YerbaValueType) -> String {
57
+ if value_type == YerbaValueType::String {
58
+ return text.to_string();
59
+ }
60
+
61
+ match resolve_plain_scalar(text) {
62
+ PlainScalar::Boolean(boolean) => boolean.to_string(),
63
+ PlainScalar::Integer(integer) => integer.to_string(),
64
+ PlainScalar::Float(float) if float.is_nan() => ".nan".to_string(),
65
+ PlainScalar::Float(float) if float.is_infinite() => (if float > 0.0 { ".inf" } else { "-.inf" }).to_string(),
66
+ PlainScalar::Float(float) => format!("{:?}", float),
67
+ PlainScalar::Null | PlainScalar::String => text.to_string(),
68
+ }
69
+ }
70
+
47
71
  #[repr(C)]
48
72
  pub struct YerbaTypedList {
49
73
  pub json: *mut c_char,
@@ -64,6 +88,26 @@ pub struct YerbaLocation {
64
88
  pub start_column: usize,
65
89
  pub end_line: usize,
66
90
  pub end_column: usize,
91
+ pub start_character_column: usize,
92
+ pub end_character_column: usize,
93
+ }
94
+
95
+ #[repr(C)]
96
+ pub struct YerbaNodeRecord {
97
+ pub parent: isize,
98
+ pub node_type: NodeType,
99
+ pub selector: *mut c_char,
100
+ pub key_name: *mut c_char,
101
+ pub value: YerbaTypedValue,
102
+ pub has_value: bool,
103
+ pub location: YerbaLocation,
104
+ pub key_location: YerbaLocation,
105
+ }
106
+
107
+ #[repr(C)]
108
+ pub struct YerbaNodeList {
109
+ pub records: *mut YerbaNodeRecord,
110
+ pub length: usize,
67
111
  }
68
112
 
69
113
  #[repr(C)]
@@ -116,11 +160,7 @@ impl YerbaGetResult {
116
160
 
117
161
  fn scalar(mut self, text: &str, value_type: YerbaValueType) -> Self {
118
162
  self.node_type = NodeType::Scalar;
119
-
120
- self.single = YerbaTypedValue {
121
- text: CString::new(text).unwrap_or_default().into_raw(),
122
- value_type,
123
- };
163
+ self.single = YerbaTypedValue::new(text, value_type);
124
164
 
125
165
  self
126
166
  }
@@ -215,6 +255,8 @@ const EMPTY_LOCATION: YerbaLocation = YerbaLocation {
215
255
  start_column: 0,
216
256
  end_line: 0,
217
257
  end_column: 0,
258
+ start_character_column: 0,
259
+ end_character_column: 0,
218
260
  };
219
261
 
220
262
  #[no_mangle]
@@ -230,11 +272,11 @@ pub unsafe extern "C" fn yerba_document_free(document: *mut Document) {
230
272
  }
231
273
 
232
274
  #[no_mangle]
233
- pub unsafe extern "C" fn yerba_document_get(document: *const Document, path: *const c_char) -> YerbaGetResult {
275
+ pub unsafe extern "C" fn yerba_document_get(document: *const Document, selector: *const c_char) -> YerbaGetResult {
234
276
  let document = &*document;
235
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
277
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
236
278
 
237
- if let Err(e) = Document::validate_path(selector_string) {
279
+ if let Err(e) = Document::validate_selector(selector_string) {
238
280
  return YerbaGetResult::with_error(&e.to_string());
239
281
  }
240
282
 
@@ -255,7 +297,7 @@ pub unsafe extern "C" fn yerba_document_get(document: *const Document, path: *co
255
297
  .iter()
256
298
  .map(|value| {
257
299
  serde_json::json!({
258
- "text": value.text,
300
+ "text": typed_text(&value.text, detect_yaml_type(value)),
259
301
  "type": detect_yaml_type(value) as u8
260
302
  })
261
303
  })
@@ -280,14 +322,29 @@ fn location_to_ffi(location: crate::Location) -> YerbaLocation {
280
322
  start_column: location.start_column,
281
323
  end_line: location.end_line,
282
324
  end_column: location.end_column,
325
+ start_character_column: location.start_character_column,
326
+ end_character_column: location.end_character_column,
283
327
  }
284
328
  }
285
329
 
330
+ fn location_json(location: &crate::Location) -> serde_json::Value {
331
+ serde_json::json!({
332
+ "start_line": location.start_line,
333
+ "start_column": location.start_column,
334
+ "end_line": location.end_line,
335
+ "end_column": location.end_column,
336
+ "start_offset": location.start_offset,
337
+ "end_offset": location.end_offset,
338
+ "start_character_column": location.start_character_column,
339
+ "end_character_column": location.end_character_column,
340
+ })
341
+ }
342
+
286
343
  /// Caller must free with yerba_string_free.
287
344
  #[no_mangle]
288
- pub unsafe extern "C" fn yerba_document_source(document: *const Document, path: *const c_char) -> *mut c_char {
345
+ pub unsafe extern "C" fn yerba_document_source(document: *const Document, selector: *const c_char) -> *mut c_char {
289
346
  let document = &*document;
290
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
347
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
291
348
 
292
349
  match document.source(selector_string) {
293
350
  Ok(text) => CString::new(text).unwrap_or_default().into_raw(),
@@ -297,14 +354,13 @@ pub unsafe extern "C" fn yerba_document_source(document: *const Document, path:
297
354
 
298
355
  /// Caller must free with yerba_string_free.
299
356
  #[no_mangle]
300
- pub unsafe extern "C" fn yerba_document_get_value(document: *const Document, path: *const c_char) -> *mut c_char {
357
+ pub unsafe extern "C" fn yerba_document_get_value(document: *const Document, selector: *const c_char) -> *mut c_char {
301
358
  let document = &*document;
302
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
359
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
303
360
 
304
361
  match document.get_value(selector_string) {
305
362
  Some(value) => {
306
- let json = crate::json::yaml_to_json(&value);
307
- let json_string = serde_json::to_string(&json).unwrap_or_else(|_| "null".to_string());
363
+ let json_string = crate::json::yaml_to_json_string_allowing_nan(&value);
308
364
 
309
365
  CString::new(json_string).unwrap_or_default().into_raw()
310
366
  }
@@ -325,9 +381,9 @@ pub unsafe extern "C" fn yerba_document_selectors(document: *const Document) ->
325
381
  }
326
382
 
327
383
  #[no_mangle]
328
- pub unsafe extern "C" fn yerba_document_resolve_selectors(document: *const Document, path: *const c_char) -> *mut c_char {
384
+ pub unsafe extern "C" fn yerba_document_resolve_selectors(document: *const Document, selector: *const c_char) -> *mut c_char {
329
385
  let document = &*document;
330
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
386
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
331
387
 
332
388
  let selectors = document.resolve_selectors(selector_string);
333
389
  let json_string = serde_json::to_string(&selectors).unwrap_or_else(|_| "[]".to_string());
@@ -336,20 +392,20 @@ pub unsafe extern "C" fn yerba_document_resolve_selectors(document: *const Docum
336
392
  }
337
393
 
338
394
  #[no_mangle]
339
- pub unsafe extern "C" fn yerba_selector_has_wildcard(path: *const c_char) -> bool {
340
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
395
+ pub unsafe extern "C" fn yerba_selector_has_wildcard(selector: *const c_char) -> bool {
396
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
341
397
 
342
398
  crate::selector::Selector::parse(selector_string).has_wildcard()
343
399
  }
344
400
 
345
401
  /// Parses a selector into JSON: `{"relative": bool, "segments": [...]}`.
346
402
  ///
347
- /// Keys are encoded as strings, indexes as integers, `[]` as `{"all": "items"}` and `*` as `{"all": "keys"}`.
403
+ /// Keys are encoded as strings, indexes as integers (negative from the end), `[]` as `{"all": "items"}` and `*` as `{"all": "keys"}`.
348
404
  #[no_mangle]
349
- pub unsafe extern "C" fn yerba_selector_parse(path: *const c_char) -> *mut c_char {
405
+ pub unsafe extern "C" fn yerba_selector_parse(selector: *const c_char) -> *mut c_char {
350
406
  use crate::selector::{Selector, SelectorSegment};
351
407
 
352
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
408
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
353
409
  let selector = Selector::parse(selector_string);
354
410
 
355
411
  let segments: Vec<serde_json::Value> = selector
@@ -358,6 +414,7 @@ pub unsafe extern "C" fn yerba_selector_parse(path: *const c_char) -> *mut c_cha
358
414
  .map(|segment| match segment {
359
415
  SelectorSegment::Key(key) => serde_json::json!(key),
360
416
  SelectorSegment::Index(index) => serde_json::json!(index),
417
+ SelectorSegment::IndexFromEnd(offset) => serde_json::json!(-(*offset.min(&(i64::MAX as usize)) as i64)),
361
418
  SelectorSegment::AllItems => serde_json::json!({ "all": "items" }),
362
419
  SelectorSegment::AllKeys => serde_json::json!({ "all": "keys" }),
363
420
  })
@@ -380,7 +437,10 @@ pub unsafe extern "C" fn yerba_selector_build(segments_json: *const c_char, rela
380
437
  .iter()
381
438
  .filter_map(|value| match value {
382
439
  serde_json::Value::String(key) => Some(SelectorSegment::Key(key.clone())),
383
- serde_json::Value::Number(number) => number.as_u64().map(|index| SelectorSegment::Index(index as usize)),
440
+ serde_json::Value::Number(number) => match number.as_i64() {
441
+ Some(index) if index < 0 => Some(SelectorSegment::IndexFromEnd(index.unsigned_abs() as usize)),
442
+ _ => number.as_u64().map(|index| SelectorSegment::Index(index as usize)),
443
+ },
384
444
  serde_json::Value::Object(object) => match object.get("all").and_then(|all| all.as_str()) {
385
445
  Some("items") => Some(SelectorSegment::AllItems),
386
446
  Some("keys") => Some(SelectorSegment::AllKeys),
@@ -401,9 +461,9 @@ pub unsafe extern "C" fn yerba_selector_build(segments_json: *const c_char, rela
401
461
  }
402
462
 
403
463
  #[no_mangle]
404
- pub unsafe extern "C" fn yerba_document_keys(document: *const Document, path: *const c_char) -> *mut c_char {
464
+ pub unsafe extern "C" fn yerba_document_keys(document: *const Document, selector: *const c_char) -> *mut c_char {
405
465
  let document = &*document;
406
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
466
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
407
467
 
408
468
  let keys = document.keys_at(selector_string);
409
469
  let json_string = serde_json::to_string(&keys).unwrap_or_else(|_| "[]".to_string());
@@ -412,9 +472,9 @@ pub unsafe extern "C" fn yerba_document_keys(document: *const Document, path: *c
412
472
  }
413
473
 
414
474
  #[no_mangle]
415
- pub unsafe extern "C" fn yerba_document_get_quote_style(document: *const Document, path: *const c_char) -> *mut c_char {
475
+ pub unsafe extern "C" fn yerba_document_get_quote_style(document: *const Document, selector: *const c_char) -> *mut c_char {
416
476
  let document = &*document;
417
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
477
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
418
478
 
419
479
  match document.get_quote_style(selector_string) {
420
480
  Some(style) => {
@@ -428,9 +488,9 @@ pub unsafe extern "C" fn yerba_document_get_quote_style(document: *const Documen
428
488
  }
429
489
 
430
490
  #[no_mangle]
431
- pub unsafe extern "C" fn yerba_document_set_quote_style(document: *mut Document, path: *const c_char, style: *const c_char) -> YerbaResult {
491
+ pub unsafe extern "C" fn yerba_document_set_quote_style(document: *mut Document, selector: *const c_char, style: *const c_char) -> YerbaResult {
432
492
  let document = &mut *document;
433
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
493
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
434
494
  let style_string = &CStr::from_ptr(style).to_str().unwrap_or("").replace('_', "-");
435
495
 
436
496
  let quote_style = match style_string.parse::<QuoteStyle>() {
@@ -445,9 +505,9 @@ pub unsafe extern "C" fn yerba_document_set_quote_style(document: *mut Document,
445
505
  }
446
506
 
447
507
  #[no_mangle]
448
- pub unsafe extern "C" fn yerba_document_get_collection_style(document: *const Document, path: *const c_char) -> *mut c_char {
508
+ pub unsafe extern "C" fn yerba_document_get_collection_style(document: *const Document, selector: *const c_char) -> *mut c_char {
449
509
  let document = &*document;
450
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
510
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
451
511
 
452
512
  match document.get_collection_style(selector_string) {
453
513
  Some(style) => CString::new(style).map(|s| s.into_raw()).unwrap_or(std::ptr::null_mut()),
@@ -456,9 +516,9 @@ pub unsafe extern "C" fn yerba_document_get_collection_style(document: *const Do
456
516
  }
457
517
 
458
518
  #[no_mangle]
459
- pub unsafe extern "C" fn yerba_document_set_collection_style(document: *mut Document, path: *const c_char, style: *const c_char) -> YerbaResult {
519
+ pub unsafe extern "C" fn yerba_document_set_collection_style(document: *mut Document, selector: *const c_char, style: *const c_char) -> YerbaResult {
460
520
  let document = &mut *document;
461
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
521
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
462
522
  let style_string = CStr::from_ptr(style).to_str().unwrap_or("");
463
523
 
464
524
  match document.set_collection_style(selector_string, style_string) {
@@ -468,9 +528,9 @@ pub unsafe extern "C" fn yerba_document_set_collection_style(document: *mut Docu
468
528
  }
469
529
 
470
530
  #[no_mangle]
471
- pub unsafe extern "C" fn yerba_document_get_sequence_indent(document: *const Document, path: *const c_char) -> *mut c_char {
531
+ pub unsafe extern "C" fn yerba_document_get_sequence_indent(document: *const Document, selector: *const c_char) -> *mut c_char {
472
532
  let document = &*document;
473
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
533
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
474
534
 
475
535
  match document.get_sequence_indent(selector_string) {
476
536
  Some(style) => CString::new(style).map(|s| s.into_raw()).unwrap_or(std::ptr::null_mut()),
@@ -479,9 +539,9 @@ pub unsafe extern "C" fn yerba_document_get_sequence_indent(document: *const Doc
479
539
  }
480
540
 
481
541
  #[no_mangle]
482
- pub unsafe extern "C" fn yerba_document_set_sequence_indent(document: *mut Document, path: *const c_char, style: *const c_char) -> YerbaResult {
542
+ pub unsafe extern "C" fn yerba_document_set_sequence_indent(document: *mut Document, selector: *const c_char, style: *const c_char) -> YerbaResult {
483
543
  let document = &mut *document;
484
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
544
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
485
545
  let style_string = CStr::from_ptr(style).to_str().unwrap_or("");
486
546
 
487
547
  match document.set_sequence_indent(selector_string, style_string) {
@@ -511,32 +571,37 @@ pub unsafe extern "C" fn yerba_validate_condition(condition: *const c_char, item
511
571
  }
512
572
 
513
573
  #[no_mangle]
514
- pub unsafe extern "C" fn yerba_document_evaluate_condition(document: *const Document, parent_path: *const c_char, condition: *const c_char) -> bool {
574
+ pub unsafe extern "C" fn yerba_document_evaluate_condition(document: *const Document, parent_selector: *const c_char, condition: *const c_char) -> bool {
515
575
  let document = &*document;
516
- let parent = CStr::from_ptr(parent_path).to_str().unwrap_or("");
576
+ let parent = CStr::from_ptr(parent_selector).to_str().unwrap_or("");
517
577
  let cond = CStr::from_ptr(condition).to_str().unwrap_or("");
518
578
 
519
579
  document.evaluate_condition(parent, cond).unwrap_or(false)
520
580
  }
521
581
 
522
582
  #[no_mangle]
523
- pub unsafe extern "C" fn yerba_document_exists(document: *const Document, path: *const c_char) -> bool {
583
+ pub unsafe extern "C" fn yerba_document_exists(document: *const Document, selector: *const c_char) -> bool {
524
584
  let document = &*document;
525
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
585
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
526
586
  document.exists(selector_string)
527
587
  }
528
588
 
529
589
  #[no_mangle]
530
- pub unsafe extern "C" fn yerba_document_valid_selector(document: *const Document, path: *const c_char) -> bool {
590
+ pub unsafe extern "C" fn yerba_document_valid_selector(document: *const Document, selector: *const c_char) -> bool {
531
591
  let document = &*document;
532
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
592
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
533
593
  document.is_valid_selector(selector_string)
534
594
  }
535
595
 
536
596
  #[no_mangle]
537
- pub unsafe extern "C" fn yerba_document_find(document: *const Document, path: *const c_char, condition: *const c_char, select: *const c_char) -> *mut c_char {
597
+ pub unsafe extern "C" fn yerba_document_find(
598
+ document: *const Document,
599
+ selector: *const c_char,
600
+ condition: *const c_char,
601
+ select: *const c_char,
602
+ ) -> *mut c_char {
538
603
  let document = &*document;
539
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
604
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
540
605
 
541
606
  let condition_string = if condition.is_null() { None } else { CStr::from_ptr(condition).to_str().ok() };
542
607
 
@@ -559,7 +624,7 @@ unsafe fn borrow_value<'a>(value: *const c_char, length: usize) -> &'a str {
559
624
  #[no_mangle]
560
625
  pub unsafe extern "C" fn yerba_document_set(
561
626
  document: *mut Document,
562
- path: *const c_char,
627
+ selector: *const c_char,
563
628
  value: *const c_char,
564
629
  value_length: usize,
565
630
  value_type: YerbaValueType,
@@ -567,7 +632,7 @@ pub unsafe extern "C" fn yerba_document_set(
567
632
  all: bool,
568
633
  ) -> YerbaResult {
569
634
  let document = &mut *document;
570
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
635
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
571
636
  let value_string = borrow_value(value, value_length);
572
637
  let verbatim = plain || value_type != YerbaValueType::String;
573
638
 
@@ -587,7 +652,7 @@ pub unsafe extern "C" fn yerba_document_set(
587
652
  #[no_mangle]
588
653
  pub unsafe extern "C" fn yerba_document_insert(
589
654
  document: *mut Document,
590
- path: *const c_char,
655
+ selector: *const c_char,
591
656
  value: *const c_char,
592
657
  value_length: usize,
593
658
  value_type: YerbaValueType,
@@ -598,7 +663,7 @@ pub unsafe extern "C" fn yerba_document_insert(
598
663
  at: i64,
599
664
  ) -> YerbaResult {
600
665
  let document = &mut *document;
601
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
666
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
602
667
  let raw_value = borrow_value(value, value_length);
603
668
 
604
669
  let value_string = match value_type {
@@ -615,10 +680,10 @@ pub unsafe extern "C" fn yerba_document_insert(
615
680
  InsertPosition::At(at as usize)
616
681
  } else if !before.is_null() {
617
682
  let target = CStr::from_ptr(before).to_str().unwrap_or("");
618
- InsertPosition::Before(target.to_string())
683
+ InsertPosition::before(target)
619
684
  } else if !after.is_null() {
620
685
  let target = CStr::from_ptr(after).to_str().unwrap_or("");
621
- InsertPosition::After(target.to_string())
686
+ InsertPosition::after(target)
622
687
  } else {
623
688
  InsertPosition::Last
624
689
  };
@@ -638,14 +703,14 @@ pub unsafe extern "C" fn yerba_document_insert(
638
703
  #[no_mangle]
639
704
  pub unsafe extern "C" fn yerba_document_insert_object(
640
705
  document: *mut Document,
641
- path: *const c_char,
706
+ selector: *const c_char,
642
707
  json: *const c_char,
643
708
  before: *const c_char,
644
709
  after: *const c_char,
645
710
  at: i64,
646
711
  ) -> YerbaResult {
647
712
  let document = &mut *document;
648
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
713
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
649
714
  let json_string = CStr::from_ptr(json).to_str().unwrap_or("");
650
715
 
651
716
  let json_value: serde_json::Value = match serde_json::from_str(json_string) {
@@ -657,10 +722,10 @@ pub unsafe extern "C" fn yerba_document_insert_object(
657
722
  InsertPosition::At(at as usize)
658
723
  } else if !before.is_null() {
659
724
  let target = CStr::from_ptr(before).to_str().unwrap_or("");
660
- InsertPosition::Before(target.to_string())
725
+ InsertPosition::before(target)
661
726
  } else if !after.is_null() {
662
727
  let target = CStr::from_ptr(after).to_str().unwrap_or("");
663
- InsertPosition::After(target.to_string())
728
+ InsertPosition::after(target)
664
729
  } else {
665
730
  InsertPosition::Last
666
731
  };
@@ -672,9 +737,9 @@ pub unsafe extern "C" fn yerba_document_insert_object(
672
737
  }
673
738
 
674
739
  #[no_mangle]
675
- pub unsafe extern "C" fn yerba_document_delete(document: *mut Document, path: *const c_char) -> YerbaResult {
740
+ pub unsafe extern "C" fn yerba_document_delete(document: *mut Document, selector: *const c_char) -> YerbaResult {
676
741
  let document = &mut *document;
677
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
742
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
678
743
 
679
744
  match document.delete(selector_string) {
680
745
  Ok(()) => YerbaResult::ok(),
@@ -683,9 +748,9 @@ pub unsafe extern "C" fn yerba_document_delete(document: *mut Document, path: *c
683
748
  }
684
749
 
685
750
  #[no_mangle]
686
- pub unsafe extern "C" fn yerba_document_insert_objects(document: *mut Document, path: *const c_char, json: *const c_char) -> YerbaResult {
751
+ pub unsafe extern "C" fn yerba_document_insert_objects(document: *mut Document, selector: *const c_char, json: *const c_char) -> YerbaResult {
687
752
  let document = &mut *document;
688
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
753
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
689
754
  let json_string = CStr::from_ptr(json).to_str().unwrap_or("");
690
755
 
691
756
  let json_values: Vec<serde_json::Value> = match serde_json::from_str(json_string) {
@@ -700,9 +765,9 @@ pub unsafe extern "C" fn yerba_document_insert_objects(document: *mut Document,
700
765
  }
701
766
 
702
767
  #[no_mangle]
703
- pub unsafe extern "C" fn yerba_document_remove(document: *mut Document, path: *const c_char, value: *const c_char) -> YerbaResult {
768
+ pub unsafe extern "C" fn yerba_document_remove(document: *mut Document, selector: *const c_char, value: *const c_char) -> YerbaResult {
704
769
  let document = &mut *document;
705
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
770
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
706
771
  let value_string = CStr::from_ptr(value).to_str().unwrap_or("");
707
772
 
708
773
  match document.remove(selector_string, value_string) {
@@ -712,9 +777,9 @@ pub unsafe extern "C" fn yerba_document_remove(document: *mut Document, path: *c
712
777
  }
713
778
 
714
779
  #[no_mangle]
715
- pub unsafe extern "C" fn yerba_document_remove_at(document: *mut Document, path: *const c_char, index: usize) -> YerbaResult {
780
+ pub unsafe extern "C" fn yerba_document_remove_at(document: *mut Document, selector: *const c_char, index: usize) -> YerbaResult {
716
781
  let document = &mut *document;
717
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
782
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
718
783
 
719
784
  match document.remove_at(selector_string, index) {
720
785
  Ok(()) => YerbaResult::ok(),
@@ -723,9 +788,9 @@ pub unsafe extern "C" fn yerba_document_remove_at(document: *mut Document, path:
723
788
  }
724
789
 
725
790
  #[no_mangle]
726
- pub unsafe extern "C" fn yerba_document_move_item(document: *mut Document, path: *const c_char, from: usize, to: usize) -> YerbaResult {
791
+ pub unsafe extern "C" fn yerba_document_move_item(document: *mut Document, selector: *const c_char, from: usize, to: usize) -> YerbaResult {
727
792
  let document = &mut *document;
728
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
793
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
729
794
 
730
795
  match document.move_item(selector_string, from, to) {
731
796
  Ok(()) => YerbaResult::ok(),
@@ -746,9 +811,9 @@ pub unsafe extern "C" fn yerba_document_rename(document: *mut Document, source:
746
811
  }
747
812
 
748
813
  #[no_mangle]
749
- pub unsafe extern "C" fn yerba_document_sort(document: *mut Document, path: *const c_char, by: *const c_char, case_sensitive: bool) -> YerbaResult {
814
+ pub unsafe extern "C" fn yerba_document_sort(document: *mut Document, selector: *const c_char, by: *const c_char, case_sensitive: bool) -> YerbaResult {
750
815
  let document = &mut *document;
751
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
816
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
752
817
 
753
818
  let by_string = if by.is_null() { None } else { CStr::from_ptr(by).to_str().ok() };
754
819
 
@@ -764,9 +829,9 @@ pub unsafe extern "C" fn yerba_document_sort(document: *mut Document, path: *con
764
829
  }
765
830
 
766
831
  #[no_mangle]
767
- pub unsafe extern "C" fn yerba_document_reorder(document: *mut Document, path: *const c_char, by: *const c_char, order_csv: *const c_char) -> YerbaResult {
832
+ pub unsafe extern "C" fn yerba_document_reorder(document: *mut Document, selector: *const c_char, by: *const c_char, order_csv: *const c_char) -> YerbaResult {
768
833
  let document = &mut *document;
769
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
834
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
770
835
  let by_string = CStr::from_ptr(by).to_str().unwrap_or("");
771
836
  let order_string = CStr::from_ptr(order_csv).to_str().unwrap_or("");
772
837
 
@@ -779,9 +844,9 @@ pub unsafe extern "C" fn yerba_document_reorder(document: *mut Document, path: *
779
844
  }
780
845
 
781
846
  #[no_mangle]
782
- pub unsafe extern "C" fn yerba_document_sort_keys(document: *mut Document, path: *const c_char, order: *const c_char) -> YerbaResult {
847
+ pub unsafe extern "C" fn yerba_document_sort_keys(document: *mut Document, selector: *const c_char, order: *const c_char) -> YerbaResult {
783
848
  let document = &mut *document;
784
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
849
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
785
850
  let order_string = CStr::from_ptr(order).to_str().unwrap_or("");
786
851
  let key_order: Vec<&str> = order_string.split(',').collect();
787
852
 
@@ -794,13 +859,13 @@ pub unsafe extern "C" fn yerba_document_sort_keys(document: *mut Document, path:
794
859
  #[no_mangle]
795
860
  pub unsafe extern "C" fn yerba_document_quote_style(
796
861
  document: *mut Document,
797
- path: *const c_char,
862
+ selector: *const c_char,
798
863
  key_style: *const c_char,
799
864
  value_style: *const c_char,
800
865
  ) -> YerbaResult {
801
866
  let document = &mut *document;
802
867
 
803
- let selector = if path.is_null() { None } else { CStr::from_ptr(path).to_str().ok() };
868
+ let selector = if selector.is_null() { None } else { CStr::from_ptr(selector).to_str().ok() };
804
869
 
805
870
  let key = if key_style.is_null() {
806
871
  None
@@ -821,9 +886,9 @@ pub unsafe extern "C" fn yerba_document_quote_style(
821
886
  }
822
887
 
823
888
  #[no_mangle]
824
- pub unsafe extern "C" fn yerba_document_blank_lines(document: *mut Document, path: *const c_char, count: usize) -> YerbaResult {
889
+ pub unsafe extern "C" fn yerba_document_blank_lines(document: *mut Document, selector: *const c_char, count: usize) -> YerbaResult {
825
890
  let document = &mut *document;
826
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
891
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
827
892
 
828
893
  match document.enforce_blank_lines(selector_string, count) {
829
894
  Ok(()) => YerbaResult::ok(),
@@ -842,7 +907,7 @@ pub unsafe extern "C" fn yerba_document_validate_schema(document: *const Documen
842
907
  let schema: serde_json::Value = match serde_json::from_str(schema_string) {
843
908
  Ok(schema) => schema,
844
909
  Err(e) => {
845
- let error = serde_json::json!([{"message": format!("invalid schema: {}", e), "path": "", "line": null}]);
910
+ let error = serde_json::json!([{"message": format!("invalid schema: {}", e), "selector": "", "line": null}]);
846
911
  return CString::new(error.to_string()).unwrap_or_default().into_raw();
847
912
  }
848
913
  };
@@ -880,13 +945,13 @@ pub unsafe extern "C" fn yerba_yerbafile_find(directory: *const c_char) -> *mut
880
945
  CStr::from_ptr(directory).to_str().ok().map(std::path::PathBuf::from)
881
946
  };
882
947
 
883
- let path = match start {
948
+ let selector = match start {
884
949
  Some(dir) => crate::Yerbafile::find_from(dir),
885
950
  None => None,
886
951
  };
887
952
 
888
- match path {
889
- Some(path) => CString::new(path.to_string_lossy().to_string()).unwrap_or_default().into_raw(),
953
+ match selector {
954
+ Some(selector) => CString::new(selector.to_string_lossy().to_string()).unwrap_or_default().into_raw(),
890
955
  None => ptr::null_mut(),
891
956
  }
892
957
  }
@@ -899,7 +964,7 @@ pub unsafe extern "C" fn yerba_document_apply_yerbafile(document: *mut Document,
899
964
 
900
965
  let yerbafile = if yerbafile_path.is_null() {
901
966
  match crate::Yerbafile::find() {
902
- Some(path) => match crate::Yerbafile::load(&path) {
967
+ Some(selector) => match crate::Yerbafile::load(&selector) {
903
968
  Ok(yerbafile) => yerbafile,
904
969
  Err(e) => return YerbaResult::err(&e.to_string()),
905
970
  },
@@ -907,9 +972,9 @@ pub unsafe extern "C" fn yerba_document_apply_yerbafile(document: *mut Document,
907
972
  None => return YerbaResult::err("No Yerbafile found"),
908
973
  }
909
974
  } else {
910
- let path = CStr::from_ptr(yerbafile_path).to_str().unwrap_or("");
975
+ let selector = CStr::from_ptr(yerbafile_path).to_str().unwrap_or("");
911
976
 
912
- match crate::Yerbafile::load(path) {
977
+ match crate::Yerbafile::load(selector) {
913
978
  Ok(yerbafile) => yerbafile,
914
979
  Err(e) => return YerbaResult::err(&e.to_string()),
915
980
  }
@@ -958,6 +1023,62 @@ pub unsafe extern "C" fn yerba_result_free(result: YerbaResult) {
958
1023
  }
959
1024
  }
960
1025
 
1026
+ #[no_mangle]
1027
+ pub unsafe extern "C" fn yerba_document_nodes(document: *const Document) -> YerbaNodeList {
1028
+ let document = &*document;
1029
+
1030
+ let records: Vec<YerbaNodeRecord> = document
1031
+ .node_records()
1032
+ .into_iter()
1033
+ .map(|record| YerbaNodeRecord {
1034
+ parent: record.parent.map(|parent| parent as isize).unwrap_or(-1),
1035
+ node_type: record.node_type,
1036
+ selector: CString::new(record.selector).unwrap_or_default().into_raw(),
1037
+ key_name: record
1038
+ .key_name
1039
+ .map(|name| CString::new(name).unwrap_or_default().into_raw())
1040
+ .unwrap_or(ptr::null_mut()),
1041
+ value: match record.scalar {
1042
+ Some(scalar) => YerbaTypedValue::new(&scalar.text, detect_yaml_type(&scalar)),
1043
+ None => YerbaTypedValue {
1044
+ text: ptr::null_mut(),
1045
+ value_type: YerbaValueType::Null,
1046
+ },
1047
+ },
1048
+ has_value: record.has_value,
1049
+ location: location_to_ffi(record.location),
1050
+ key_location: location_to_ffi(record.key_location),
1051
+ })
1052
+ .collect();
1053
+
1054
+ let mut records = records.into_boxed_slice();
1055
+ let list = YerbaNodeList {
1056
+ records: records.as_mut_ptr(),
1057
+ length: records.len(),
1058
+ };
1059
+
1060
+ std::mem::forget(records);
1061
+
1062
+ list
1063
+ }
1064
+
1065
+ #[no_mangle]
1066
+ pub unsafe extern "C" fn yerba_node_list_free(list: YerbaNodeList) {
1067
+ if list.records.is_null() {
1068
+ return;
1069
+ }
1070
+
1071
+ let records = Box::from_raw(std::ptr::slice_from_raw_parts_mut(list.records, list.length));
1072
+
1073
+ for record in records.iter() {
1074
+ for pointer in [record.selector, record.key_name, record.value.text] {
1075
+ if !pointer.is_null() {
1076
+ drop(CString::from_raw(pointer));
1077
+ }
1078
+ }
1079
+ }
1080
+ }
1081
+
961
1082
  #[no_mangle]
962
1083
  pub unsafe extern "C" fn yerba_get_result_free(result: YerbaGetResult) {
963
1084
  if !result.single.text.is_null() {
@@ -981,14 +1102,7 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
981
1102
  "node_type": node.node_type,
982
1103
  "selector": node.selector,
983
1104
  "line": node.line,
984
- "location": {
985
- "start_line": node.location.start_line,
986
- "start_column": node.location.start_column,
987
- "end_line": node.location.end_line,
988
- "end_column": node.location.end_column,
989
- "start_offset": node.location.start_offset,
990
- "end_offset": node.location.end_offset,
991
- },
1105
+ "location": location_json(&node.location),
992
1106
  });
993
1107
 
994
1108
  if let Some(file_path) = &node.file_path {
@@ -996,7 +1110,7 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
996
1110
  }
997
1111
 
998
1112
  if let Some(text) = &node.text {
999
- value["text"] = serde_json::json!(text);
1113
+ value["text"] = serde_json::json!(typed_text(text, node.value_type.unwrap_or(YerbaValueType::String)));
1000
1114
  }
1001
1115
 
1002
1116
  if let Some(vt) = node.value_type {
@@ -1005,14 +1119,7 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
1005
1119
 
1006
1120
  if let Some(key_name) = &node.key_name {
1007
1121
  value["key_name"] = serde_json::json!(key_name);
1008
- value["key_location"] = serde_json::json!({
1009
- "start_line": node.key_location.start_line,
1010
- "start_column": node.key_location.start_column,
1011
- "end_line": node.key_location.end_line,
1012
- "end_column": node.key_location.end_column,
1013
- "start_offset": node.key_location.start_offset,
1014
- "end_offset": node.key_location.end_offset,
1015
- });
1122
+ value["key_location"] = location_json(&node.key_location);
1016
1123
  }
1017
1124
 
1018
1125
  value
@@ -1030,26 +1137,31 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
1030
1137
 
1031
1138
  #[cfg(feature = "glob")]
1032
1139
  #[no_mangle]
1033
- pub unsafe extern "C" fn yerba_glob_get(glob_pattern: *const c_char, path: *const c_char) -> YerbaTypedList {
1140
+ pub unsafe extern "C" fn yerba_glob_get(glob_pattern: *const c_char, selector: *const c_char) -> YerbaTypedList {
1034
1141
  let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
1035
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
1142
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
1036
1143
 
1037
1144
  located_nodes_to_list(&crate::glob_get(pattern, selector_string))
1038
1145
  }
1039
1146
 
1040
1147
  #[no_mangle]
1041
- pub unsafe extern "C" fn yerba_document_get_all(document: *const Document, path: *const c_char) -> YerbaTypedList {
1148
+ pub unsafe extern "C" fn yerba_document_get_all(document: *const Document, selector: *const c_char) -> YerbaTypedList {
1042
1149
  let document = &*document;
1043
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
1150
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
1044
1151
 
1045
1152
  located_nodes_to_list(&document.get_all_located(selector_string))
1046
1153
  }
1047
1154
 
1048
1155
  #[cfg(feature = "glob")]
1049
1156
  #[no_mangle]
1050
- pub unsafe extern "C" fn yerba_glob_find(glob_pattern: *const c_char, path: *const c_char, condition: *const c_char, select: *const c_char) -> YerbaTypedList {
1157
+ pub unsafe extern "C" fn yerba_glob_find(
1158
+ glob_pattern: *const c_char,
1159
+ selector: *const c_char,
1160
+ condition: *const c_char,
1161
+ select: *const c_char,
1162
+ ) -> YerbaTypedList {
1051
1163
  let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
1052
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
1164
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
1053
1165
  let condition_string = if condition.is_null() { None } else { CStr::from_ptr(condition).to_str().ok() };
1054
1166
  let select_string = if select.is_null() { None } else { CStr::from_ptr(select).to_str().ok() };
1055
1167