yerba 0.9.1-arm-linux-gnu → 0.10.0-arm-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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -16
  3. data/exe/arm-linux-gnu/yerba +0 -0
  4. data/ext/yerba/include/yerba.h +67 -32
  5. data/ext/yerba/yerba.c +296 -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 +142 -0
  19. data/lib/yerba/sequence.rb +38 -33
  20. data/lib/yerba/version.rb +1 -1
  21. data/lib/yerba.rb +1 -0
  22. data/rust/Cargo.lock +1 -1
  23. data/rust/Cargo.toml +1 -1
  24. data/rust/src/commands/get.rs +12 -12
  25. data/rust/src/commands/init.rs +8 -8
  26. data/rust/src/commands/insert.rs +4 -18
  27. data/rust/src/commands/location.rs +2 -0
  28. data/rust/src/commands/mod.rs +34 -6
  29. data/rust/src/commands/move_item.rs +1 -1
  30. data/rust/src/commands/move_key.rs +8 -8
  31. data/rust/src/commands/rename.rs +1 -1
  32. data/rust/src/commands/selectors.rs +1 -1
  33. data/rust/src/commands/set.rs +14 -6
  34. data/rust/src/document/condition.rs +25 -25
  35. data/rust/src/document/delete.rs +57 -43
  36. data/rust/src/document/get.rs +91 -82
  37. data/rust/src/document/insert.rs +77 -77
  38. data/rust/src/document/mod.rs +138 -64
  39. data/rust/src/document/nodes.rs +162 -0
  40. data/rust/src/document/schema.rs +8 -8
  41. data/rust/src/document/set.rs +49 -26
  42. data/rust/src/document/sort.rs +54 -54
  43. data/rust/src/document/style.rs +50 -49
  44. data/rust/src/document/unique.rs +5 -5
  45. data/rust/src/error.rs +8 -4
  46. data/rust/src/ffi.rs +272 -102
  47. data/rust/src/json.rs +62 -2
  48. data/rust/src/lib.rs +2 -1
  49. data/rust/src/main.rs +2 -1
  50. data/rust/src/selector.rs +48 -7
  51. data/rust/src/syntax.rs +449 -56
  52. data/rust/src/validation.rs +5 -3
  53. data/rust/src/yerbafile.rs +124 -76
  54. metadata +4 -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,16 +392,78 @@ 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
 
401
+ /// Parses a selector into JSON: `{"relative": bool, "segments": [...]}`.
402
+ ///
403
+ /// Keys are encoded as strings, indexes as integers (negative from the end), `[]` as `{"all": "items"}` and `*` as `{"all": "keys"}`.
404
+ #[no_mangle]
405
+ pub unsafe extern "C" fn yerba_selector_parse(selector: *const c_char) -> *mut c_char {
406
+ use crate::selector::{Selector, SelectorSegment};
407
+
408
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
409
+ let selector = Selector::parse(selector_string);
410
+
411
+ let segments: Vec<serde_json::Value> = selector
412
+ .segments()
413
+ .iter()
414
+ .map(|segment| match segment {
415
+ SelectorSegment::Key(key) => serde_json::json!(key),
416
+ SelectorSegment::Index(index) => serde_json::json!(index),
417
+ SelectorSegment::IndexFromEnd(offset) => serde_json::json!(-(*offset.min(&(i64::MAX as usize)) as i64)),
418
+ SelectorSegment::AllItems => serde_json::json!({ "all": "items" }),
419
+ SelectorSegment::AllKeys => serde_json::json!({ "all": "keys" }),
420
+ })
421
+ .collect();
422
+
423
+ let json = serde_json::json!({ "relative": selector.is_relative(), "segments": segments });
424
+
425
+ CString::new(json.to_string()).unwrap_or_default().into_raw()
426
+ }
427
+
428
+ /// Builds a selector string from a JSON array of segments, encoded like `yerba_selector_parse` returns them.
345
429
  #[no_mangle]
346
- pub unsafe extern "C" fn yerba_document_keys(document: *const Document, path: *const c_char) -> *mut c_char {
430
+ pub unsafe extern "C" fn yerba_selector_build(segments_json: *const c_char, relative: bool) -> *mut c_char {
431
+ use crate::selector::{Selector, SelectorSegment};
432
+
433
+ let json_string = CStr::from_ptr(segments_json).to_str().unwrap_or("[]");
434
+ let values: Vec<serde_json::Value> = serde_json::from_str(json_string).unwrap_or_default();
435
+
436
+ let segments: Vec<SelectorSegment> = values
437
+ .iter()
438
+ .filter_map(|value| match value {
439
+ serde_json::Value::String(key) => Some(SelectorSegment::Key(key.clone())),
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
+ },
444
+ serde_json::Value::Object(object) => match object.get("all").and_then(|all| all.as_str()) {
445
+ Some("items") => Some(SelectorSegment::AllItems),
446
+ Some("keys") => Some(SelectorSegment::AllKeys),
447
+ _ => None,
448
+ },
449
+ _ => None,
450
+ })
451
+ .collect();
452
+
453
+ let selector_string = Selector::Absolute(segments).to_selector_string();
454
+ let selector_string = if relative && !selector_string.is_empty() {
455
+ format!(".{}", selector_string)
456
+ } else {
457
+ selector_string
458
+ };
459
+
460
+ CString::new(selector_string).unwrap_or_default().into_raw()
461
+ }
462
+
463
+ #[no_mangle]
464
+ pub unsafe extern "C" fn yerba_document_keys(document: *const Document, selector: *const c_char) -> *mut c_char {
347
465
  let document = &*document;
348
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
466
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
349
467
 
350
468
  let keys = document.keys_at(selector_string);
351
469
  let json_string = serde_json::to_string(&keys).unwrap_or_else(|_| "[]".to_string());
@@ -354,9 +472,9 @@ pub unsafe extern "C" fn yerba_document_keys(document: *const Document, path: *c
354
472
  }
355
473
 
356
474
  #[no_mangle]
357
- 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 {
358
476
  let document = &*document;
359
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
477
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
360
478
 
361
479
  match document.get_quote_style(selector_string) {
362
480
  Some(style) => {
@@ -370,9 +488,9 @@ pub unsafe extern "C" fn yerba_document_get_quote_style(document: *const Documen
370
488
  }
371
489
 
372
490
  #[no_mangle]
373
- 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 {
374
492
  let document = &mut *document;
375
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
493
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
376
494
  let style_string = &CStr::from_ptr(style).to_str().unwrap_or("").replace('_', "-");
377
495
 
378
496
  let quote_style = match style_string.parse::<QuoteStyle>() {
@@ -387,9 +505,9 @@ pub unsafe extern "C" fn yerba_document_set_quote_style(document: *mut Document,
387
505
  }
388
506
 
389
507
  #[no_mangle]
390
- 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 {
391
509
  let document = &*document;
392
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
510
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
393
511
 
394
512
  match document.get_collection_style(selector_string) {
395
513
  Some(style) => CString::new(style).map(|s| s.into_raw()).unwrap_or(std::ptr::null_mut()),
@@ -398,9 +516,9 @@ pub unsafe extern "C" fn yerba_document_get_collection_style(document: *const Do
398
516
  }
399
517
 
400
518
  #[no_mangle]
401
- 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 {
402
520
  let document = &mut *document;
403
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
521
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
404
522
  let style_string = CStr::from_ptr(style).to_str().unwrap_or("");
405
523
 
406
524
  match document.set_collection_style(selector_string, style_string) {
@@ -410,9 +528,9 @@ pub unsafe extern "C" fn yerba_document_set_collection_style(document: *mut Docu
410
528
  }
411
529
 
412
530
  #[no_mangle]
413
- 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 {
414
532
  let document = &*document;
415
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
533
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
416
534
 
417
535
  match document.get_sequence_indent(selector_string) {
418
536
  Some(style) => CString::new(style).map(|s| s.into_raw()).unwrap_or(std::ptr::null_mut()),
@@ -421,9 +539,9 @@ pub unsafe extern "C" fn yerba_document_get_sequence_indent(document: *const Doc
421
539
  }
422
540
 
423
541
  #[no_mangle]
424
- 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 {
425
543
  let document = &mut *document;
426
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
544
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
427
545
  let style_string = CStr::from_ptr(style).to_str().unwrap_or("");
428
546
 
429
547
  match document.set_sequence_indent(selector_string, style_string) {
@@ -453,32 +571,37 @@ pub unsafe extern "C" fn yerba_validate_condition(condition: *const c_char, item
453
571
  }
454
572
 
455
573
  #[no_mangle]
456
- 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 {
457
575
  let document = &*document;
458
- let parent = CStr::from_ptr(parent_path).to_str().unwrap_or("");
576
+ let parent = CStr::from_ptr(parent_selector).to_str().unwrap_or("");
459
577
  let cond = CStr::from_ptr(condition).to_str().unwrap_or("");
460
578
 
461
579
  document.evaluate_condition(parent, cond).unwrap_or(false)
462
580
  }
463
581
 
464
582
  #[no_mangle]
465
- 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 {
466
584
  let document = &*document;
467
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
585
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
468
586
  document.exists(selector_string)
469
587
  }
470
588
 
471
589
  #[no_mangle]
472
- 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 {
473
591
  let document = &*document;
474
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
592
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
475
593
  document.is_valid_selector(selector_string)
476
594
  }
477
595
 
478
596
  #[no_mangle]
479
- 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 {
480
603
  let document = &*document;
481
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
604
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
482
605
 
483
606
  let condition_string = if condition.is_null() { None } else { CStr::from_ptr(condition).to_str().ok() };
484
607
 
@@ -501,7 +624,7 @@ unsafe fn borrow_value<'a>(value: *const c_char, length: usize) -> &'a str {
501
624
  #[no_mangle]
502
625
  pub unsafe extern "C" fn yerba_document_set(
503
626
  document: *mut Document,
504
- path: *const c_char,
627
+ selector: *const c_char,
505
628
  value: *const c_char,
506
629
  value_length: usize,
507
630
  value_type: YerbaValueType,
@@ -509,7 +632,7 @@ pub unsafe extern "C" fn yerba_document_set(
509
632
  all: bool,
510
633
  ) -> YerbaResult {
511
634
  let document = &mut *document;
512
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
635
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
513
636
  let value_string = borrow_value(value, value_length);
514
637
  let verbatim = plain || value_type != YerbaValueType::String;
515
638
 
@@ -529,7 +652,7 @@ pub unsafe extern "C" fn yerba_document_set(
529
652
  #[no_mangle]
530
653
  pub unsafe extern "C" fn yerba_document_insert(
531
654
  document: *mut Document,
532
- path: *const c_char,
655
+ selector: *const c_char,
533
656
  value: *const c_char,
534
657
  value_length: usize,
535
658
  value_type: YerbaValueType,
@@ -540,7 +663,7 @@ pub unsafe extern "C" fn yerba_document_insert(
540
663
  at: i64,
541
664
  ) -> YerbaResult {
542
665
  let document = &mut *document;
543
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
666
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
544
667
  let raw_value = borrow_value(value, value_length);
545
668
 
546
669
  let value_string = match value_type {
@@ -557,10 +680,10 @@ pub unsafe extern "C" fn yerba_document_insert(
557
680
  InsertPosition::At(at as usize)
558
681
  } else if !before.is_null() {
559
682
  let target = CStr::from_ptr(before).to_str().unwrap_or("");
560
- InsertPosition::Before(target.to_string())
683
+ InsertPosition::before(target)
561
684
  } else if !after.is_null() {
562
685
  let target = CStr::from_ptr(after).to_str().unwrap_or("");
563
- InsertPosition::After(target.to_string())
686
+ InsertPosition::after(target)
564
687
  } else {
565
688
  InsertPosition::Last
566
689
  };
@@ -580,14 +703,14 @@ pub unsafe extern "C" fn yerba_document_insert(
580
703
  #[no_mangle]
581
704
  pub unsafe extern "C" fn yerba_document_insert_object(
582
705
  document: *mut Document,
583
- path: *const c_char,
706
+ selector: *const c_char,
584
707
  json: *const c_char,
585
708
  before: *const c_char,
586
709
  after: *const c_char,
587
710
  at: i64,
588
711
  ) -> YerbaResult {
589
712
  let document = &mut *document;
590
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
713
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
591
714
  let json_string = CStr::from_ptr(json).to_str().unwrap_or("");
592
715
 
593
716
  let json_value: serde_json::Value = match serde_json::from_str(json_string) {
@@ -599,10 +722,10 @@ pub unsafe extern "C" fn yerba_document_insert_object(
599
722
  InsertPosition::At(at as usize)
600
723
  } else if !before.is_null() {
601
724
  let target = CStr::from_ptr(before).to_str().unwrap_or("");
602
- InsertPosition::Before(target.to_string())
725
+ InsertPosition::before(target)
603
726
  } else if !after.is_null() {
604
727
  let target = CStr::from_ptr(after).to_str().unwrap_or("");
605
- InsertPosition::After(target.to_string())
728
+ InsertPosition::after(target)
606
729
  } else {
607
730
  InsertPosition::Last
608
731
  };
@@ -614,9 +737,9 @@ pub unsafe extern "C" fn yerba_document_insert_object(
614
737
  }
615
738
 
616
739
  #[no_mangle]
617
- 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 {
618
741
  let document = &mut *document;
619
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
742
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
620
743
 
621
744
  match document.delete(selector_string) {
622
745
  Ok(()) => YerbaResult::ok(),
@@ -625,9 +748,9 @@ pub unsafe extern "C" fn yerba_document_delete(document: *mut Document, path: *c
625
748
  }
626
749
 
627
750
  #[no_mangle]
628
- 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 {
629
752
  let document = &mut *document;
630
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
753
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
631
754
  let json_string = CStr::from_ptr(json).to_str().unwrap_or("");
632
755
 
633
756
  let json_values: Vec<serde_json::Value> = match serde_json::from_str(json_string) {
@@ -642,9 +765,9 @@ pub unsafe extern "C" fn yerba_document_insert_objects(document: *mut Document,
642
765
  }
643
766
 
644
767
  #[no_mangle]
645
- 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 {
646
769
  let document = &mut *document;
647
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
770
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
648
771
  let value_string = CStr::from_ptr(value).to_str().unwrap_or("");
649
772
 
650
773
  match document.remove(selector_string, value_string) {
@@ -654,9 +777,9 @@ pub unsafe extern "C" fn yerba_document_remove(document: *mut Document, path: *c
654
777
  }
655
778
 
656
779
  #[no_mangle]
657
- 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 {
658
781
  let document = &mut *document;
659
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
782
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
660
783
 
661
784
  match document.remove_at(selector_string, index) {
662
785
  Ok(()) => YerbaResult::ok(),
@@ -665,9 +788,9 @@ pub unsafe extern "C" fn yerba_document_remove_at(document: *mut Document, path:
665
788
  }
666
789
 
667
790
  #[no_mangle]
668
- 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 {
669
792
  let document = &mut *document;
670
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
793
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
671
794
 
672
795
  match document.move_item(selector_string, from, to) {
673
796
  Ok(()) => YerbaResult::ok(),
@@ -688,9 +811,9 @@ pub unsafe extern "C" fn yerba_document_rename(document: *mut Document, source:
688
811
  }
689
812
 
690
813
  #[no_mangle]
691
- 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 {
692
815
  let document = &mut *document;
693
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
816
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
694
817
 
695
818
  let by_string = if by.is_null() { None } else { CStr::from_ptr(by).to_str().ok() };
696
819
 
@@ -706,9 +829,9 @@ pub unsafe extern "C" fn yerba_document_sort(document: *mut Document, path: *con
706
829
  }
707
830
 
708
831
  #[no_mangle]
709
- 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 {
710
833
  let document = &mut *document;
711
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
834
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
712
835
  let by_string = CStr::from_ptr(by).to_str().unwrap_or("");
713
836
  let order_string = CStr::from_ptr(order_csv).to_str().unwrap_or("");
714
837
 
@@ -721,9 +844,9 @@ pub unsafe extern "C" fn yerba_document_reorder(document: *mut Document, path: *
721
844
  }
722
845
 
723
846
  #[no_mangle]
724
- 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 {
725
848
  let document = &mut *document;
726
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
849
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
727
850
  let order_string = CStr::from_ptr(order).to_str().unwrap_or("");
728
851
  let key_order: Vec<&str> = order_string.split(',').collect();
729
852
 
@@ -736,13 +859,13 @@ pub unsafe extern "C" fn yerba_document_sort_keys(document: *mut Document, path:
736
859
  #[no_mangle]
737
860
  pub unsafe extern "C" fn yerba_document_quote_style(
738
861
  document: *mut Document,
739
- path: *const c_char,
862
+ selector: *const c_char,
740
863
  key_style: *const c_char,
741
864
  value_style: *const c_char,
742
865
  ) -> YerbaResult {
743
866
  let document = &mut *document;
744
867
 
745
- 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() };
746
869
 
747
870
  let key = if key_style.is_null() {
748
871
  None
@@ -763,9 +886,9 @@ pub unsafe extern "C" fn yerba_document_quote_style(
763
886
  }
764
887
 
765
888
  #[no_mangle]
766
- 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 {
767
890
  let document = &mut *document;
768
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
891
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
769
892
 
770
893
  match document.enforce_blank_lines(selector_string, count) {
771
894
  Ok(()) => YerbaResult::ok(),
@@ -784,7 +907,7 @@ pub unsafe extern "C" fn yerba_document_validate_schema(document: *const Documen
784
907
  let schema: serde_json::Value = match serde_json::from_str(schema_string) {
785
908
  Ok(schema) => schema,
786
909
  Err(e) => {
787
- 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}]);
788
911
  return CString::new(error.to_string()).unwrap_or_default().into_raw();
789
912
  }
790
913
  };
@@ -822,13 +945,13 @@ pub unsafe extern "C" fn yerba_yerbafile_find(directory: *const c_char) -> *mut
822
945
  CStr::from_ptr(directory).to_str().ok().map(std::path::PathBuf::from)
823
946
  };
824
947
 
825
- let path = match start {
948
+ let selector = match start {
826
949
  Some(dir) => crate::Yerbafile::find_from(dir),
827
950
  None => None,
828
951
  };
829
952
 
830
- match path {
831
- 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(),
832
955
  None => ptr::null_mut(),
833
956
  }
834
957
  }
@@ -841,7 +964,7 @@ pub unsafe extern "C" fn yerba_document_apply_yerbafile(document: *mut Document,
841
964
 
842
965
  let yerbafile = if yerbafile_path.is_null() {
843
966
  match crate::Yerbafile::find() {
844
- Some(path) => match crate::Yerbafile::load(&path) {
967
+ Some(selector) => match crate::Yerbafile::load(&selector) {
845
968
  Ok(yerbafile) => yerbafile,
846
969
  Err(e) => return YerbaResult::err(&e.to_string()),
847
970
  },
@@ -849,9 +972,9 @@ pub unsafe extern "C" fn yerba_document_apply_yerbafile(document: *mut Document,
849
972
  None => return YerbaResult::err("No Yerbafile found"),
850
973
  }
851
974
  } else {
852
- let path = CStr::from_ptr(yerbafile_path).to_str().unwrap_or("");
975
+ let selector = CStr::from_ptr(yerbafile_path).to_str().unwrap_or("");
853
976
 
854
- match crate::Yerbafile::load(path) {
977
+ match crate::Yerbafile::load(selector) {
855
978
  Ok(yerbafile) => yerbafile,
856
979
  Err(e) => return YerbaResult::err(&e.to_string()),
857
980
  }
@@ -900,6 +1023,62 @@ pub unsafe extern "C" fn yerba_result_free(result: YerbaResult) {
900
1023
  }
901
1024
  }
902
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
+
903
1082
  #[no_mangle]
904
1083
  pub unsafe extern "C" fn yerba_get_result_free(result: YerbaGetResult) {
905
1084
  if !result.single.text.is_null() {
@@ -923,14 +1102,7 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
923
1102
  "node_type": node.node_type,
924
1103
  "selector": node.selector,
925
1104
  "line": node.line,
926
- "location": {
927
- "start_line": node.location.start_line,
928
- "start_column": node.location.start_column,
929
- "end_line": node.location.end_line,
930
- "end_column": node.location.end_column,
931
- "start_offset": node.location.start_offset,
932
- "end_offset": node.location.end_offset,
933
- },
1105
+ "location": location_json(&node.location),
934
1106
  });
935
1107
 
936
1108
  if let Some(file_path) = &node.file_path {
@@ -938,7 +1110,7 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
938
1110
  }
939
1111
 
940
1112
  if let Some(text) = &node.text {
941
- value["text"] = serde_json::json!(text);
1113
+ value["text"] = serde_json::json!(typed_text(text, node.value_type.unwrap_or(YerbaValueType::String)));
942
1114
  }
943
1115
 
944
1116
  if let Some(vt) = node.value_type {
@@ -947,14 +1119,7 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
947
1119
 
948
1120
  if let Some(key_name) = &node.key_name {
949
1121
  value["key_name"] = serde_json::json!(key_name);
950
- value["key_location"] = serde_json::json!({
951
- "start_line": node.key_location.start_line,
952
- "start_column": node.key_location.start_column,
953
- "end_line": node.key_location.end_line,
954
- "end_column": node.key_location.end_column,
955
- "start_offset": node.key_location.start_offset,
956
- "end_offset": node.key_location.end_offset,
957
- });
1122
+ value["key_location"] = location_json(&node.key_location);
958
1123
  }
959
1124
 
960
1125
  value
@@ -972,26 +1137,31 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
972
1137
 
973
1138
  #[cfg(feature = "glob")]
974
1139
  #[no_mangle]
975
- 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 {
976
1141
  let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
977
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
1142
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
978
1143
 
979
1144
  located_nodes_to_list(&crate::glob_get(pattern, selector_string))
980
1145
  }
981
1146
 
982
1147
  #[no_mangle]
983
- 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 {
984
1149
  let document = &*document;
985
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
1150
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
986
1151
 
987
1152
  located_nodes_to_list(&document.get_all_located(selector_string))
988
1153
  }
989
1154
 
990
1155
  #[cfg(feature = "glob")]
991
1156
  #[no_mangle]
992
- 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 {
993
1163
  let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
994
- let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
1164
+ let selector_string = CStr::from_ptr(selector).to_str().unwrap_or("");
995
1165
  let condition_string = if condition.is_null() { None } else { CStr::from_ptr(condition).to_str().ok() };
996
1166
  let select_string = if select.is_null() { None } else { CStr::from_ptr(select).to_str().ok() };
997
1167