yerba 0.1.2 → 0.2.0

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +492 -15
  3. data/ext/yerba/extconf.rb +87 -30
  4. data/ext/yerba/include/yerba.h +168 -0
  5. data/ext/yerba/yerba.c +752 -0
  6. data/lib/yerba/collection.rb +31 -0
  7. data/lib/yerba/document.rb +59 -0
  8. data/lib/yerba/formatting.rb +18 -0
  9. data/lib/yerba/location.rb +5 -0
  10. data/lib/yerba/map.rb +166 -0
  11. data/lib/yerba/scalar.rb +85 -0
  12. data/lib/yerba/sequence.rb +182 -0
  13. data/lib/yerba/version.rb +1 -1
  14. data/lib/yerba.rb +30 -4
  15. data/rust/Cargo.lock +378 -2
  16. data/rust/Cargo.toml +5 -1
  17. data/rust/build.rs +11 -0
  18. data/rust/cbindgen.toml +27 -0
  19. data/rust/src/commands/apply.rs +5 -0
  20. data/rust/src/commands/blank_lines.rs +58 -0
  21. data/rust/src/commands/check.rs +5 -0
  22. data/rust/src/commands/delete.rs +35 -0
  23. data/rust/src/commands/get.rs +194 -0
  24. data/rust/src/commands/init.rs +89 -0
  25. data/rust/src/commands/insert.rs +106 -0
  26. data/rust/src/commands/mate.rs +55 -0
  27. data/rust/src/commands/mod.rs +349 -0
  28. data/rust/src/commands/move_item.rs +54 -0
  29. data/rust/src/commands/move_key.rs +87 -0
  30. data/rust/src/commands/quote_style.rs +62 -0
  31. data/rust/src/commands/remove.rs +35 -0
  32. data/rust/src/commands/rename.rs +37 -0
  33. data/rust/src/commands/set.rs +59 -0
  34. data/rust/src/commands/sort.rs +52 -0
  35. data/rust/src/commands/sort_keys.rs +62 -0
  36. data/rust/src/commands/version.rs +8 -0
  37. data/rust/src/document.rs +764 -333
  38. data/rust/src/error.rs +0 -5
  39. data/rust/src/ffi.rs +991 -0
  40. data/rust/src/json.rs +49 -90
  41. data/rust/src/lib.rs +9 -2
  42. data/rust/src/main.rs +55 -843
  43. data/rust/src/selector.rs +241 -0
  44. data/rust/src/syntax.rs +97 -21
  45. data/rust/src/yaml_writer.rs +89 -0
  46. data/rust/src/yerbafile.rs +11 -126
  47. data/yerba.gemspec +4 -0
  48. metadata +33 -1
data/rust/src/json.rs CHANGED
@@ -1,3 +1,5 @@
1
+ use crate::selector::{Selector, SelectorSegment};
2
+
1
3
  pub fn yaml_to_json(value: &serde_yaml::Value) -> serde_json::Value {
2
4
  match value {
3
5
  serde_yaml::Value::Null => serde_json::Value::Null,
@@ -37,53 +39,54 @@ pub fn yaml_to_json(value: &serde_yaml::Value) -> serde_json::Value {
37
39
  }
38
40
 
39
41
  pub fn resolve_select_field(value: &serde_yaml::Value, field: &str) -> serde_json::Value {
40
- if !field.contains('.') && !field.contains('[') {
41
- if let serde_yaml::Value::Mapping(map) = value {
42
- for (key, yaml_value) in map {
43
- if let serde_yaml::Value::String(key_string) = key {
44
- if key_string == field {
45
- return yaml_to_json(yaml_value);
42
+ let parsed = Selector::parse(field);
43
+ let segments = parsed.segments();
44
+
45
+ if segments.len() == 1 {
46
+ if let SelectorSegment::Key(key) = &segments[0] {
47
+ if let serde_yaml::Value::Mapping(map) = value {
48
+ for (map_key, yaml_value) in map {
49
+ if let serde_yaml::Value::String(key_string) = map_key {
50
+ if key_string == key {
51
+ return yaml_to_json(yaml_value);
52
+ }
46
53
  }
47
54
  }
48
55
  }
49
- }
50
56
 
51
- return serde_json::Value::Null;
57
+ return serde_json::Value::Null;
58
+ }
52
59
  }
53
60
 
54
61
  let mut current_values = vec![value.clone()];
55
62
 
56
- for segment in parse_select_segments(field) {
63
+ for segment in segments {
57
64
  let mut next_values = Vec::new();
58
65
 
59
66
  for current in &current_values {
60
- if segment.starts_with('[') {
61
- if let serde_yaml::Value::Sequence(sequence) = current {
62
- let index = segment
63
- .strip_prefix('[')
64
- .and_then(|rest| rest.strip_suffix(']'))
65
- .and_then(|inner| {
66
- if inner.is_empty() {
67
- None
68
- } else {
69
- inner.parse::<usize>().ok()
70
- }
71
- });
67
+ match segment {
68
+ SelectorSegment::AllItems => {
69
+ if let serde_yaml::Value::Sequence(sequence) = current {
70
+ next_values.extend(sequence.iter().cloned());
71
+ }
72
+ }
72
73
 
73
- match index {
74
- None => next_values.extend(sequence.iter().cloned()),
75
- Some(index) => {
76
- if let Some(item) = sequence.get(index) {
77
- next_values.push(item.clone());
78
- }
74
+ SelectorSegment::Index(index) => {
75
+ if let serde_yaml::Value::Sequence(sequence) = current {
76
+ if let Some(item) = sequence.get(*index) {
77
+ next_values.push(item.clone());
79
78
  }
80
79
  }
81
80
  }
82
- } else if let serde_yaml::Value::Mapping(map) = current {
83
- for (map_key, yaml_value) in map {
84
- if let serde_yaml::Value::String(key_string) = map_key {
85
- if key_string == segment {
86
- next_values.push(yaml_value.clone());
81
+
82
+ SelectorSegment::Key(key) => {
83
+ if let serde_yaml::Value::Mapping(map) = current {
84
+ for (map_key, yaml_value) in map {
85
+ if let serde_yaml::Value::String(key_string) = map_key {
86
+ if key_string == key {
87
+ next_values.push(yaml_value.clone());
88
+ }
89
+ }
87
90
  }
88
91
  }
89
92
  }
@@ -93,15 +96,15 @@ pub fn resolve_select_field(value: &serde_yaml::Value, field: &str) -> serde_jso
93
96
  current_values = next_values;
94
97
  }
95
98
 
96
- let used_brackets = field.contains("[]");
99
+ let used_all_items = parsed.segments().iter().any(|s| matches!(s, SelectorSegment::AllItems));
97
100
 
98
101
  if current_values.is_empty() {
99
- if used_brackets {
102
+ if used_all_items {
100
103
  serde_json::Value::Array(Vec::new())
101
104
  } else {
102
105
  serde_json::Value::Null
103
106
  }
104
- } else if current_values.len() == 1 && !used_brackets {
107
+ } else if current_values.len() == 1 && !used_all_items {
105
108
  yaml_to_json(&current_values[0])
106
109
  } else {
107
110
  serde_json::Value::Array(current_values.iter().map(yaml_to_json).collect())
@@ -109,61 +112,17 @@ pub fn resolve_select_field(value: &serde_yaml::Value, field: &str) -> serde_jso
109
112
  }
110
113
 
111
114
  pub fn select_field_key(field: &str) -> String {
112
- let root = field.split(['.', '[']).next().unwrap_or(field);
113
-
114
- root.to_string()
115
- }
116
-
117
- fn parse_select_segments(field: &str) -> Vec<&str> {
118
- let mut segments = Vec::new();
119
- let mut rest = field;
120
-
121
- while !rest.is_empty() {
122
- if rest.starts_with('[') {
123
- if let Some(close) = rest.find(']') {
124
- segments.push(&rest[..close + 1]);
125
- rest = &rest[close + 1..];
126
-
127
- if rest.starts_with('.') {
128
- rest = &rest[1..];
129
- }
115
+ let parsed = Selector::parse(field);
116
+
117
+ parsed
118
+ .segments()
119
+ .iter()
120
+ .find_map(|segment| {
121
+ if let SelectorSegment::Key(key) = segment {
122
+ Some(key.clone())
130
123
  } else {
131
- segments.push(rest);
132
- break;
133
- }
134
- } else {
135
- let dot_index = rest.find('.');
136
- let bracket_index = rest.find('[');
137
-
138
- let split_at = match (dot_index, bracket_index) {
139
- (Some(dot), Some(bracket)) => Some(dot.min(bracket)),
140
- (Some(dot), None) => Some(dot),
141
- (None, Some(bracket)) => Some(bracket),
142
- (None, None) => None,
143
- };
144
-
145
- match split_at {
146
- Some(index) => {
147
- let segment = &rest[..index];
148
-
149
- if !segment.is_empty() {
150
- segments.push(segment);
151
- }
152
-
153
- rest = &rest[index..];
154
-
155
- if rest.starts_with('.') {
156
- rest = &rest[1..];
157
- }
158
- }
159
-
160
- None => {
161
- segments.push(rest);
162
- break;
163
- }
124
+ None
164
125
  }
165
- }
166
- }
167
-
168
- segments
126
+ })
127
+ .unwrap_or_else(|| field.to_string())
169
128
  }
data/rust/src/lib.rs CHANGED
@@ -1,13 +1,20 @@
1
1
  mod document;
2
2
  mod error;
3
+ pub mod ffi;
4
+ pub mod json;
3
5
  mod quote_style;
6
+ pub mod selector;
4
7
  mod syntax;
8
+ mod yaml_writer;
5
9
  pub mod yerbafile;
6
10
 
7
- pub use document::{Document, FindResult, InsertPosition, SortField};
11
+ pub use document::{Document, InsertPosition, SortField};
8
12
  pub use error::YerbaError;
9
13
  pub use quote_style::QuoteStyle;
10
- pub use yerbafile::{resolve_template, Variable, Yerbafile};
14
+ pub use selector::Selector;
15
+ pub use syntax::{detect_yaml_type, ScalarValue, YerbaValueType};
16
+ pub use yaml_writer::json_to_yaml_text;
17
+ pub use yerbafile::Yerbafile;
11
18
 
12
19
  pub fn version() -> &'static str {
13
20
  env!("CARGO_PKG_VERSION")