yerba 0.3.0-aarch64-linux-gnu → 0.4.1-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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +93 -8
  3. data/exe/aarch64-linux-gnu/yerba +0 -0
  4. data/ext/yerba/extconf.rb +22 -3
  5. data/ext/yerba/include/yerba.h +32 -9
  6. data/ext/yerba/yerba.c +133 -25
  7. data/lib/yerba/3.2/yerba.so +0 -0
  8. data/lib/yerba/3.3/yerba.so +0 -0
  9. data/lib/yerba/3.4/yerba.so +0 -0
  10. data/lib/yerba/4.0/yerba.so +0 -0
  11. data/lib/yerba/collection.rb +35 -0
  12. data/lib/yerba/document.rb +45 -3
  13. data/lib/yerba/query_result.rb +50 -0
  14. data/lib/yerba/sequence.rb +187 -1
  15. data/lib/yerba/version.rb +1 -1
  16. data/lib/yerba/yerbafile.rb +45 -0
  17. data/lib/yerba.rb +2 -0
  18. data/rust/Cargo.lock +3 -1
  19. data/rust/Cargo.toml +3 -2
  20. data/rust/cbindgen.toml +1 -0
  21. data/rust/rustfmt.toml +1 -1
  22. data/rust/src/commands/apply.rs +11 -2
  23. data/rust/src/commands/blank_lines.rs +1 -4
  24. data/rust/src/commands/check.rs +11 -2
  25. data/rust/src/commands/directives.rs +61 -0
  26. data/rust/src/commands/get.rs +5 -22
  27. data/rust/src/commands/mod.rs +16 -18
  28. data/rust/src/commands/quote_style.rs +12 -6
  29. data/rust/src/commands/selectors.rs +3 -19
  30. data/rust/src/commands/sort.rs +22 -157
  31. data/rust/src/didyoumean.rs +2 -4
  32. data/rust/src/document/condition.rs +139 -0
  33. data/rust/src/document/delete.rs +91 -0
  34. data/rust/src/document/get.rs +262 -0
  35. data/rust/src/document/insert.rs +384 -0
  36. data/rust/src/document/mod.rs +784 -0
  37. data/rust/src/document/set.rs +100 -0
  38. data/rust/src/document/sort.rs +639 -0
  39. data/rust/src/document/style.rs +473 -0
  40. data/rust/src/error.rs +24 -6
  41. data/rust/src/ffi.rs +272 -518
  42. data/rust/src/json.rs +1 -7
  43. data/rust/src/lib.rs +88 -2
  44. data/rust/src/main.rs +2 -0
  45. data/rust/src/quote_style.rs +83 -7
  46. data/rust/src/selector.rs +2 -7
  47. data/rust/src/syntax.rs +41 -21
  48. data/rust/src/yerbafile.rs +86 -19
  49. metadata +13 -3
  50. data/rust/src/document.rs +0 -2304
@@ -0,0 +1,91 @@
1
+ use super::*;
2
+
3
+ impl Document {
4
+ pub fn rename(&mut self, source_path: &str, destination_path: &str) -> Result<(), YerbaError> {
5
+ Self::validate_path(source_path)?;
6
+ Self::validate_path(destination_path)?;
7
+
8
+ let source_parent = source_path.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
9
+ let destination_parent = destination_path.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
10
+ let destination_key = destination_path.rsplit_once('.').map(|(_, key)| key).unwrap_or(destination_path);
11
+
12
+ if source_parent == destination_parent {
13
+ let (parent_path, source_key) = source_path.rsplit_once('.').unwrap_or(("", source_path));
14
+ let parent_node = self.navigate(parent_path)?;
15
+
16
+ let map = parent_node
17
+ .descendants()
18
+ .find_map(BlockMap::cast)
19
+ .ok_or_else(|| YerbaError::SelectorNotFound(source_path.to_string()))?;
20
+
21
+ let entry = find_entry_by_key(&map, source_key).ok_or_else(|| YerbaError::SelectorNotFound(source_path.to_string()))?;
22
+ let key_node = entry.key().ok_or_else(|| YerbaError::SelectorNotFound(source_path.to_string()))?;
23
+ let key_token = find_scalar_token(key_node.syntax()).ok_or_else(|| YerbaError::SelectorNotFound(source_path.to_string()))?;
24
+ let new_text = format_scalar_value(destination_key, key_token.kind());
25
+
26
+ self.replace_token(&key_token, &new_text)
27
+ } else {
28
+ let value = self.get(source_path).ok_or_else(|| YerbaError::SelectorNotFound(source_path.to_string()))?;
29
+
30
+ self.delete(source_path)?;
31
+ self.insert_into(destination_path, &value, InsertPosition::Last)
32
+ }
33
+ }
34
+
35
+ pub fn delete(&mut self, dot_path: &str) -> Result<(), YerbaError> {
36
+ Self::validate_path(dot_path)?;
37
+
38
+ let (parent_path, last_key) = dot_path.rsplit_once('.').unwrap_or(("", dot_path));
39
+ let parent_node = self.navigate(parent_path)?;
40
+
41
+ let map = parent_node
42
+ .descendants()
43
+ .find_map(BlockMap::cast)
44
+ .ok_or_else(|| YerbaError::SelectorNotFound(dot_path.to_string()))?;
45
+
46
+ let entry = find_entry_by_key(&map, last_key).ok_or_else(|| YerbaError::SelectorNotFound(dot_path.to_string()))?;
47
+
48
+ self.remove_node(entry.syntax())
49
+ }
50
+
51
+ pub fn remove(&mut self, dot_path: &str, value: &str) -> Result<(), YerbaError> {
52
+ let current_node = self.navigate(dot_path)?;
53
+
54
+ let sequence = current_node
55
+ .descendants()
56
+ .find_map(BlockSeq::cast)
57
+ .ok_or_else(|| YerbaError::NotASequence(dot_path.to_string()))?;
58
+
59
+ let target_entry = sequence
60
+ .entries()
61
+ .find(|entry| {
62
+ entry
63
+ .flow()
64
+ .and_then(|flow| extract_scalar_text(flow.syntax()))
65
+ .map(|text| text == value)
66
+ .unwrap_or(false)
67
+ })
68
+ .ok_or_else(|| YerbaError::SelectorNotFound(format!("{} item '{}'", dot_path, value)))?;
69
+
70
+ self.remove_node(target_entry.syntax())
71
+ }
72
+
73
+ pub fn remove_at(&mut self, dot_path: &str, index: usize) -> Result<(), YerbaError> {
74
+ Self::validate_path(dot_path)?;
75
+
76
+ let current_node = self.navigate(dot_path)?;
77
+
78
+ let sequence = current_node
79
+ .descendants()
80
+ .find_map(BlockSeq::cast)
81
+ .ok_or_else(|| YerbaError::NotASequence(dot_path.to_string()))?;
82
+
83
+ let entries: Vec<_> = sequence.entries().collect();
84
+
85
+ if index >= entries.len() {
86
+ return Err(YerbaError::IndexOutOfBounds(index, entries.len()));
87
+ }
88
+
89
+ self.remove_node(entries[index].syntax())
90
+ }
91
+ }
@@ -0,0 +1,262 @@
1
+ use super::*;
2
+
3
+ impl Document {
4
+ pub fn get(&self, dot_path: &str) -> Option<String> {
5
+ if dot_path.contains('[') {
6
+ return self.get_all(dot_path).into_iter().next();
7
+ }
8
+
9
+ let current_node = self.navigate(dot_path).ok()?;
10
+
11
+ extract_scalar_text(&current_node)
12
+ }
13
+
14
+ pub fn get_all(&self, dot_path: &str) -> Vec<String> {
15
+ self.navigate_all(dot_path).iter().filter_map(extract_scalar_text).collect()
16
+ }
17
+
18
+ pub fn get_typed(&self, dot_path: &str) -> Option<ScalarValue> {
19
+ if crate::selector::Selector::parse(dot_path).has_wildcard() {
20
+ return self.get_all_typed(dot_path).into_iter().next();
21
+ }
22
+
23
+ let current_node = self.navigate(dot_path).ok()?;
24
+
25
+ if current_node
26
+ .descendants()
27
+ .any(|child| child.kind() == SyntaxKind::BLOCK_MAP || child.kind() == SyntaxKind::BLOCK_SEQ)
28
+ {
29
+ return None;
30
+ }
31
+
32
+ extract_scalar(&current_node)
33
+ }
34
+
35
+ pub fn get_all_typed(&self, dot_path: &str) -> Vec<ScalarValue> {
36
+ self
37
+ .navigate_all(dot_path)
38
+ .iter()
39
+ .filter(|node| {
40
+ !node
41
+ .descendants()
42
+ .any(|child| child.kind() == SyntaxKind::BLOCK_MAP || child.kind() == SyntaxKind::BLOCK_SEQ)
43
+ })
44
+ .filter_map(extract_scalar)
45
+ .collect()
46
+ }
47
+
48
+ pub fn node_type(&self, dot_path: &str) -> NodeType {
49
+ match self.navigate(dot_path) {
50
+ Ok(node) => {
51
+ if let Some(first_structural) = node
52
+ .descendants()
53
+ .find(|child| BlockMap::can_cast(child.kind()) || BlockSeq::can_cast(child.kind()))
54
+ {
55
+ if BlockMap::can_cast(first_structural.kind()) {
56
+ NodeType::Map
57
+ } else {
58
+ NodeType::Sequence
59
+ }
60
+ } else if extract_scalar(&node).is_some() {
61
+ NodeType::Scalar
62
+ } else {
63
+ NodeType::NotFound
64
+ }
65
+ }
66
+ Err(_) => NodeType::NotFound,
67
+ }
68
+ }
69
+
70
+ pub fn get_node_info(&self, dot_path: &str) -> NodeInfo {
71
+ let selector = crate::selector::Selector::parse(dot_path);
72
+ let source = self.root.text().to_string();
73
+
74
+ let (location, key_name, key_location) = self.resolve_location(dot_path, &source);
75
+
76
+ if selector.has_wildcard() {
77
+ let values = self.get_all_typed(dot_path);
78
+
79
+ return NodeInfo {
80
+ node_type: NodeType::Sequence,
81
+ is_list: true,
82
+ value: None,
83
+ list_values: values,
84
+ location,
85
+ key_name,
86
+ key_location,
87
+ };
88
+ }
89
+
90
+ match self.get_typed(dot_path) {
91
+ Some(scalar) => NodeInfo {
92
+ node_type: NodeType::Scalar,
93
+ is_list: false,
94
+ value: Some(scalar),
95
+ list_values: vec![],
96
+ location,
97
+ key_name,
98
+ key_location,
99
+ },
100
+ None => NodeInfo {
101
+ node_type: self.node_type(dot_path),
102
+ is_list: false,
103
+ value: None,
104
+ list_values: vec![],
105
+ location,
106
+ key_name,
107
+ key_location,
108
+ },
109
+ }
110
+ }
111
+
112
+ fn resolve_location(&self, dot_path: &str, source: &str) -> (Location, Option<String>, Location) {
113
+ match self.navigate(dot_path) {
114
+ Ok(node) => {
115
+ let range = node.text_range();
116
+ let location = compute_location(source, range.start().into(), range.end().into());
117
+
118
+ let (key_name, key_location) = node
119
+ .parent()
120
+ .and_then(|parent| {
121
+ use yaml_parser::ast::BlockMapEntry;
122
+
123
+ BlockMapEntry::cast(parent).and_then(|entry| {
124
+ entry.key().and_then(|key_node| {
125
+ let key_text = extract_scalar_text(key_node.syntax())?;
126
+ let key_range = key_node.syntax().text_range();
127
+ let key_location = compute_location(source, key_range.start().into(), key_range.end().into());
128
+
129
+ Some((key_text, key_location))
130
+ })
131
+ })
132
+ })
133
+ .map(|(name, location)| (Some(name), location))
134
+ .unwrap_or((None, Location::default()));
135
+
136
+ (location, key_name, key_location)
137
+ }
138
+ Err(_) => (Location::default(), None, Location::default()),
139
+ }
140
+ }
141
+
142
+ pub fn find_items(&self, dot_path: &str, condition: Option<&str>, select: Option<&str>) -> Vec<serde_json::Value> {
143
+ let values = match condition {
144
+ Some(cond) => self.filter(dot_path, cond),
145
+ None => self.get_values(dot_path),
146
+ };
147
+
148
+ let select_fields: Option<Vec<&str>> = select.map(|s| s.split(',').collect());
149
+
150
+ values
151
+ .iter()
152
+ .map(|value| match &select_fields {
153
+ Some(fields) => {
154
+ let mut result = serde_json::Map::new();
155
+
156
+ for field in fields {
157
+ let json_value = crate::json::resolve_select_field(value, field);
158
+ let json_key = crate::json::select_field_key(field);
159
+ result.insert(json_key, json_value);
160
+ }
161
+
162
+ serde_json::Value::Object(result)
163
+ }
164
+ None => crate::json::yaml_to_json(value),
165
+ })
166
+ .collect()
167
+ }
168
+
169
+ pub fn get_value(&self, dot_path: &str) -> Option<serde_yaml::Value> {
170
+ if dot_path.is_empty() {
171
+ return Some(node_to_yaml_value(&self.root));
172
+ }
173
+
174
+ let nodes = self.navigate_all(dot_path);
175
+
176
+ if nodes.is_empty() {
177
+ return None;
178
+ }
179
+
180
+ if nodes.len() == 1 {
181
+ return Some(node_to_yaml_value(&nodes[0]));
182
+ }
183
+
184
+ let values: Vec<serde_yaml::Value> = nodes.iter().map(node_to_yaml_value).collect();
185
+
186
+ Some(serde_yaml::Value::Sequence(values))
187
+ }
188
+
189
+ pub fn get_values(&self, dot_path: &str) -> Vec<serde_yaml::Value> {
190
+ self.navigate_all(dot_path).iter().map(node_to_yaml_value).collect()
191
+ }
192
+
193
+ pub fn selectors(&self) -> Vec<String> {
194
+ let Some(value) = self.get_value("") else {
195
+ return Vec::new();
196
+ };
197
+
198
+ let mut selectors = Vec::new();
199
+
200
+ collect_selectors(&value, "", &mut selectors);
201
+ selectors.sort();
202
+ selectors.dedup();
203
+
204
+ selectors
205
+ }
206
+
207
+ pub fn exists(&self, dot_path: &str) -> bool {
208
+ if dot_path.contains('[') {
209
+ return !self.navigate_all(dot_path).is_empty();
210
+ }
211
+
212
+ self.get(dot_path).is_some()
213
+ }
214
+
215
+ pub fn get_sequence_values(&self, dot_path: &str) -> Vec<String> {
216
+ let current_node = match self.navigate(dot_path) {
217
+ Ok(node) => node,
218
+ Err(_) => return Vec::new(),
219
+ };
220
+
221
+ let sequence = match current_node.descendants().find_map(BlockSeq::cast) {
222
+ Some(sequence) => sequence,
223
+ None => return Vec::new(),
224
+ };
225
+
226
+ sequence
227
+ .entries()
228
+ .filter_map(|entry| entry.flow().and_then(|flow| extract_scalar_text(flow.syntax())))
229
+ .collect()
230
+ }
231
+
232
+ pub fn get_quote_style(&self, dot_path: &str) -> Option<&'static str> {
233
+ let current_node = self.navigate(dot_path).ok()?;
234
+
235
+ for element in current_node.descendants_with_tokens() {
236
+ match element.kind() {
237
+ SyntaxKind::PLAIN_SCALAR => return Some("plain"),
238
+ SyntaxKind::SINGLE_QUOTED_SCALAR => return Some("single"),
239
+ SyntaxKind::DOUBLE_QUOTED_SCALAR => return Some("double"),
240
+
241
+ SyntaxKind::BLOCK_SCALAR => {
242
+ let text = element.as_node()?.text().to_string();
243
+ let header = text.lines().next().unwrap_or("").trim();
244
+
245
+ return match header {
246
+ "|-" => Some("literal"),
247
+ "|" => Some("literal-clip"),
248
+ "|+" => Some("literal-keep"),
249
+ ">-" => Some("folded"),
250
+ ">" => Some("folded-clip"),
251
+ ">+" => Some("folded-keep"),
252
+ _ => None,
253
+ };
254
+ }
255
+
256
+ _ => {}
257
+ }
258
+ }
259
+
260
+ None
261
+ }
262
+ }