yerba 0.2.2 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +167 -12
- data/ext/yerba/extconf.rb +39 -12
- data/ext/yerba/include/yerba.h +21 -10
- data/ext/yerba/yerba.c +91 -25
- data/lib/yerba/collection.rb +35 -0
- data/lib/yerba/document.rb +16 -0
- data/lib/yerba/sequence.rb +169 -1
- data/lib/yerba/version.rb +1 -1
- data/lib/yerba.rb +7 -2
- data/rust/Cargo.lock +1 -0
- data/rust/Cargo.toml +2 -2
- data/rust/cbindgen.toml +1 -0
- data/rust/rustfmt.toml +1 -1
- data/rust/src/commands/blank_lines.rs +1 -4
- data/rust/src/commands/delete.rs +9 -4
- data/rust/src/commands/directives.rs +61 -0
- data/rust/src/commands/get.rs +52 -26
- data/rust/src/commands/insert.rs +8 -4
- data/rust/src/commands/mod.rs +71 -9
- data/rust/src/commands/move_item.rs +2 -1
- data/rust/src/commands/move_key.rs +2 -1
- data/rust/src/commands/quote_style.rs +12 -6
- data/rust/src/commands/remove.rs +8 -4
- data/rust/src/commands/rename.rs +8 -4
- data/rust/src/commands/selectors.rs +158 -0
- data/rust/src/commands/set.rs +33 -16
- data/rust/src/commands/sort.rs +342 -10
- data/rust/src/didyoumean.rs +53 -0
- data/rust/src/document/condition.rs +139 -0
- data/rust/src/document/delete.rs +91 -0
- data/rust/src/document/get.rs +262 -0
- data/rust/src/document/insert.rs +314 -0
- data/rust/src/document/mod.rs +784 -0
- data/rust/src/document/set.rs +90 -0
- data/rust/src/document/sort.rs +607 -0
- data/rust/src/document/style.rs +473 -0
- data/rust/src/error.rs +35 -7
- data/rust/src/ffi.rs +213 -520
- data/rust/src/json.rs +1 -7
- data/rust/src/lib.rs +89 -2
- data/rust/src/main.rs +2 -0
- data/rust/src/quote_style.rs +83 -7
- data/rust/src/selector.rs +2 -7
- data/rust/src/syntax.rs +41 -21
- data/rust/src/yerbafile.rs +39 -18
- metadata +12 -2
- data/rust/Cargo.lock +0 -805
- data/rust/src/document.rs +0 -2237
data/rust/src/ffi.rs
CHANGED
|
@@ -12,10 +12,8 @@ use std::ffi::{CStr, CString};
|
|
|
12
12
|
use std::os::raw::c_char;
|
|
13
13
|
use std::ptr;
|
|
14
14
|
|
|
15
|
-
use yaml_parser::SyntaxKind;
|
|
16
|
-
|
|
17
|
-
use crate::selector::Selector;
|
|
18
15
|
use crate::syntax::{detect_yaml_type, YerbaValueType};
|
|
16
|
+
use crate::NodeType;
|
|
19
17
|
use crate::{Document, InsertPosition, QuoteStyle};
|
|
20
18
|
|
|
21
19
|
#[repr(C)]
|
|
@@ -52,15 +50,6 @@ pub struct YerbaTypedList {
|
|
|
52
50
|
pub length: usize,
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
#[repr(C)]
|
|
56
|
-
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
57
|
-
pub enum YerbaNodeType {
|
|
58
|
-
Scalar = 0,
|
|
59
|
-
Map = 1,
|
|
60
|
-
Sequence = 2,
|
|
61
|
-
NotFound = 3,
|
|
62
|
-
}
|
|
63
|
-
|
|
64
53
|
#[repr(C)]
|
|
65
54
|
pub struct YerbaParseResult {
|
|
66
55
|
pub document: *mut Document,
|
|
@@ -80,7 +69,7 @@ pub struct YerbaLocation {
|
|
|
80
69
|
#[repr(C)]
|
|
81
70
|
pub struct YerbaGetResult {
|
|
82
71
|
pub is_list: bool,
|
|
83
|
-
pub node_type:
|
|
72
|
+
pub node_type: NodeType,
|
|
84
73
|
pub single: YerbaTypedValue,
|
|
85
74
|
pub list: YerbaTypedList,
|
|
86
75
|
pub location: YerbaLocation,
|
|
@@ -89,6 +78,72 @@ pub struct YerbaGetResult {
|
|
|
89
78
|
pub error: *mut c_char,
|
|
90
79
|
}
|
|
91
80
|
|
|
81
|
+
impl YerbaGetResult {
|
|
82
|
+
fn empty() -> Self {
|
|
83
|
+
YerbaGetResult {
|
|
84
|
+
is_list: false,
|
|
85
|
+
node_type: NodeType::NotFound,
|
|
86
|
+
single: YerbaTypedValue {
|
|
87
|
+
text: ptr::null_mut(),
|
|
88
|
+
value_type: YerbaValueType::Null,
|
|
89
|
+
},
|
|
90
|
+
list: YerbaTypedList {
|
|
91
|
+
json: ptr::null_mut(),
|
|
92
|
+
length: 0,
|
|
93
|
+
},
|
|
94
|
+
location: EMPTY_LOCATION,
|
|
95
|
+
key_name: ptr::null_mut(),
|
|
96
|
+
key_location: EMPTY_LOCATION,
|
|
97
|
+
error: ptr::null_mut(),
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fn with_error(error: &str) -> Self {
|
|
102
|
+
let mut result = Self::empty();
|
|
103
|
+
|
|
104
|
+
result.error = CString::new(error).unwrap_or_default().into_raw();
|
|
105
|
+
|
|
106
|
+
result
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fn with_location(mut self, location: YerbaLocation, key_name: *mut c_char, key_location: YerbaLocation) -> Self {
|
|
110
|
+
self.location = location;
|
|
111
|
+
self.key_name = key_name;
|
|
112
|
+
self.key_location = key_location;
|
|
113
|
+
|
|
114
|
+
self
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
fn scalar(mut self, text: &str, value_type: YerbaValueType) -> Self {
|
|
118
|
+
self.node_type = NodeType::Scalar;
|
|
119
|
+
|
|
120
|
+
self.single = YerbaTypedValue {
|
|
121
|
+
text: CString::new(text).unwrap_or_default().into_raw(),
|
|
122
|
+
value_type,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
self
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fn list(mut self, json: &str, length: usize) -> Self {
|
|
129
|
+
self.is_list = true;
|
|
130
|
+
self.node_type = NodeType::Sequence;
|
|
131
|
+
|
|
132
|
+
self.list = YerbaTypedList {
|
|
133
|
+
json: CString::new(json).unwrap_or_default().into_raw(),
|
|
134
|
+
length,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
self
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
fn with_node_type(mut self, node_type: NodeType) -> Self {
|
|
141
|
+
self.node_type = node_type;
|
|
142
|
+
|
|
143
|
+
self
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
92
147
|
#[no_mangle]
|
|
93
148
|
pub unsafe extern "C" fn yerba_document_parse_file(path: *const c_char) -> YerbaParseResult {
|
|
94
149
|
if path.is_null() {
|
|
@@ -98,19 +153,17 @@ pub unsafe extern "C" fn yerba_document_parse_file(path: *const c_char) -> Yerba
|
|
|
98
153
|
};
|
|
99
154
|
}
|
|
100
155
|
|
|
101
|
-
let
|
|
156
|
+
let file_path = match CStr::from_ptr(path).to_str() {
|
|
102
157
|
Ok(string) => string,
|
|
103
158
|
Err(e) => {
|
|
104
159
|
return YerbaParseResult {
|
|
105
160
|
document: ptr::null_mut(),
|
|
106
|
-
error: CString::new(format!("Invalid UTF-8 in path: {}", e))
|
|
107
|
-
.unwrap_or_default()
|
|
108
|
-
.into_raw(),
|
|
161
|
+
error: CString::new(format!("Invalid UTF-8 in path: {}", e)).unwrap_or_default().into_raw(),
|
|
109
162
|
}
|
|
110
163
|
}
|
|
111
164
|
};
|
|
112
165
|
|
|
113
|
-
match Document::parse_file(
|
|
166
|
+
match Document::parse_file(file_path) {
|
|
114
167
|
Ok(document) => YerbaParseResult {
|
|
115
168
|
document: Box::into_raw(Box::new(document)),
|
|
116
169
|
error: ptr::null_mut(),
|
|
@@ -137,9 +190,7 @@ pub unsafe extern "C" fn yerba_document_parse(content: *const c_char) -> YerbaPa
|
|
|
137
190
|
Err(e) => {
|
|
138
191
|
return YerbaParseResult {
|
|
139
192
|
document: ptr::null_mut(),
|
|
140
|
-
error: CString::new(format!("Invalid UTF-8: {}", e))
|
|
141
|
-
.unwrap_or_default()
|
|
142
|
-
.into_raw(),
|
|
193
|
+
error: CString::new(format!("Invalid UTF-8: {}", e)).unwrap_or_default().into_raw(),
|
|
143
194
|
}
|
|
144
195
|
}
|
|
145
196
|
};
|
|
@@ -157,28 +208,6 @@ pub unsafe extern "C" fn yerba_document_parse(content: *const c_char) -> YerbaPa
|
|
|
157
208
|
}
|
|
158
209
|
}
|
|
159
210
|
|
|
160
|
-
fn compute_location(source: &str, start_offset: usize, end_offset: usize) -> YerbaLocation {
|
|
161
|
-
let start = start_offset.min(source.len());
|
|
162
|
-
let end = end_offset.min(source.len());
|
|
163
|
-
|
|
164
|
-
let before_start = &source[..start];
|
|
165
|
-
let start_line = before_start.chars().filter(|c| *c == '\n').count() + 1;
|
|
166
|
-
let start_column = start - before_start.rfind('\n').map(|p| p + 1).unwrap_or(0);
|
|
167
|
-
|
|
168
|
-
let before_end = &source[..end];
|
|
169
|
-
let end_line = before_end.chars().filter(|c| *c == '\n').count() + 1;
|
|
170
|
-
let end_column = end - before_end.rfind('\n').map(|p| p + 1).unwrap_or(0);
|
|
171
|
-
|
|
172
|
-
YerbaLocation {
|
|
173
|
-
start_offset: start,
|
|
174
|
-
end_offset: end,
|
|
175
|
-
start_line,
|
|
176
|
-
start_column,
|
|
177
|
-
end_line,
|
|
178
|
-
end_column,
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
211
|
const EMPTY_LOCATION: YerbaLocation = YerbaLocation {
|
|
183
212
|
start_offset: 0,
|
|
184
213
|
end_offset: 0,
|
|
@@ -198,173 +227,71 @@ pub unsafe extern "C" fn yerba_document_free(document: *mut Document) {
|
|
|
198
227
|
#[no_mangle]
|
|
199
228
|
pub unsafe extern "C" fn yerba_document_get(document: *const Document, path: *const c_char) -> YerbaGetResult {
|
|
200
229
|
let document = &*document;
|
|
201
|
-
let
|
|
202
|
-
|
|
203
|
-
let selector = Selector::parse(path_string);
|
|
230
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
204
231
|
|
|
205
|
-
if let Err(e) = Document::validate_path(
|
|
206
|
-
return YerbaGetResult
|
|
207
|
-
is_list: false,
|
|
208
|
-
node_type: YerbaNodeType::NotFound,
|
|
209
|
-
single: YerbaTypedValue {
|
|
210
|
-
text: ptr::null_mut(),
|
|
211
|
-
value_type: YerbaValueType::Null,
|
|
212
|
-
},
|
|
213
|
-
list: YerbaTypedList {
|
|
214
|
-
json: ptr::null_mut(),
|
|
215
|
-
length: 0,
|
|
216
|
-
},
|
|
217
|
-
key_name: ptr::null_mut(),
|
|
218
|
-
key_location: EMPTY_LOCATION,
|
|
219
|
-
location: EMPTY_LOCATION,
|
|
220
|
-
error: CString::new(e.to_string()).unwrap_or_default().into_raw(),
|
|
221
|
-
};
|
|
232
|
+
if let Err(e) = Document::validate_path(selector_string) {
|
|
233
|
+
return YerbaGetResult::with_error(&e.to_string());
|
|
222
234
|
}
|
|
223
235
|
|
|
224
|
-
let
|
|
225
|
-
|
|
226
|
-
let
|
|
227
|
-
Ok(node) => {
|
|
228
|
-
let range = node.text_range();
|
|
229
|
-
let location = compute_location(&source, range.start().into(), range.end().into());
|
|
230
|
-
|
|
231
|
-
let (key_text, key_location) = node
|
|
232
|
-
.parent()
|
|
233
|
-
.and_then(|parent| {
|
|
234
|
-
use rowan::ast::AstNode;
|
|
235
|
-
use yaml_parser::ast::BlockMapEntry;
|
|
236
|
+
let info = document.get_node_info(selector_string);
|
|
237
|
+
let location = location_to_ffi(info.location);
|
|
238
|
+
let key_location = location_to_ffi(info.key_location);
|
|
236
239
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
let key_text = crate::syntax::extract_scalar_text(key_node.syntax())?;
|
|
240
|
-
let key_range = key_node.syntax().text_range();
|
|
241
|
-
let key_location = compute_location(&source, key_range.start().into(), key_range.end().into());
|
|
242
|
-
|
|
243
|
-
Some((key_text, key_location))
|
|
244
|
-
})
|
|
245
|
-
})
|
|
246
|
-
})
|
|
247
|
-
.map(|(name, location)| (Some(name), location))
|
|
248
|
-
.unwrap_or((None, EMPTY_LOCATION));
|
|
249
|
-
|
|
250
|
-
(location, key_text, key_location)
|
|
251
|
-
}
|
|
252
|
-
Err(_) => (EMPTY_LOCATION, None, EMPTY_LOCATION),
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
let key_name_pointer = key_text
|
|
240
|
+
let key_name = info
|
|
241
|
+
.key_name
|
|
256
242
|
.map(|name| CString::new(name).unwrap_or_default().into_raw())
|
|
257
243
|
.unwrap_or(ptr::null_mut());
|
|
258
244
|
|
|
259
|
-
|
|
260
|
-
let values = document.get_all_typed(path_string);
|
|
245
|
+
let base = YerbaGetResult::empty().with_location(location, key_name, key_location);
|
|
261
246
|
|
|
262
|
-
|
|
247
|
+
if info.is_list {
|
|
248
|
+
let typed: Vec<serde_json::Value> = info
|
|
249
|
+
.list_values
|
|
263
250
|
.iter()
|
|
264
|
-
.map(|
|
|
251
|
+
.map(|value| {
|
|
265
252
|
serde_json::json!({
|
|
266
|
-
"text":
|
|
267
|
-
"type": detect_yaml_type(
|
|
253
|
+
"text": value.text,
|
|
254
|
+
"type": detect_yaml_type(value) as u8
|
|
268
255
|
})
|
|
269
256
|
})
|
|
270
257
|
.collect();
|
|
271
258
|
|
|
272
259
|
let json = serde_json::to_string(&typed).unwrap_or_else(|_| "[]".to_string());
|
|
273
|
-
let length = values.len();
|
|
274
260
|
|
|
275
|
-
|
|
276
|
-
is_list: true,
|
|
277
|
-
node_type: YerbaNodeType::Sequence,
|
|
278
|
-
single: YerbaTypedValue {
|
|
279
|
-
text: ptr::null_mut(),
|
|
280
|
-
value_type: YerbaValueType::Null,
|
|
281
|
-
},
|
|
282
|
-
list: YerbaTypedList {
|
|
283
|
-
json: CString::new(json).unwrap_or_default().into_raw(),
|
|
284
|
-
length,
|
|
285
|
-
},
|
|
286
|
-
location,
|
|
287
|
-
key_name: key_name_pointer,
|
|
288
|
-
key_location,
|
|
289
|
-
error: ptr::null_mut(),
|
|
290
|
-
}
|
|
261
|
+
base.list(&json, info.list_values.len())
|
|
291
262
|
} else {
|
|
292
|
-
match
|
|
293
|
-
Some(scalar) =>
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
YerbaGetResult {
|
|
297
|
-
is_list: false,
|
|
298
|
-
node_type: YerbaNodeType::Scalar,
|
|
299
|
-
single: YerbaTypedValue {
|
|
300
|
-
text: CString::new(scalar.text).unwrap_or_default().into_raw(),
|
|
301
|
-
value_type: vtype,
|
|
302
|
-
},
|
|
303
|
-
list: YerbaTypedList {
|
|
304
|
-
json: ptr::null_mut(),
|
|
305
|
-
length: 0,
|
|
306
|
-
},
|
|
307
|
-
location,
|
|
308
|
-
key_name: key_name_pointer,
|
|
309
|
-
key_location,
|
|
310
|
-
error: ptr::null_mut(),
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
None => {
|
|
315
|
-
use rowan::ast::AstNode;
|
|
316
|
-
use yaml_parser::ast::{BlockMap, BlockSeq};
|
|
317
|
-
|
|
318
|
-
let node_type = match document.navigate(path_string) {
|
|
319
|
-
Ok(node) => {
|
|
320
|
-
if node.children().any(|child| BlockSeq::can_cast(child.kind())) {
|
|
321
|
-
YerbaNodeType::Sequence
|
|
322
|
-
} else if node.children().any(|child| BlockMap::can_cast(child.kind())) {
|
|
323
|
-
YerbaNodeType::Map
|
|
324
|
-
} else if node.descendants().any(|child| BlockSeq::can_cast(child.kind())) {
|
|
325
|
-
YerbaNodeType::Sequence
|
|
326
|
-
} else if node.descendants().any(|child| BlockMap::can_cast(child.kind())) {
|
|
327
|
-
YerbaNodeType::Map
|
|
328
|
-
} else {
|
|
329
|
-
YerbaNodeType::NotFound
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
Err(_) => YerbaNodeType::NotFound,
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
YerbaGetResult {
|
|
336
|
-
is_list: false,
|
|
337
|
-
node_type,
|
|
338
|
-
single: YerbaTypedValue {
|
|
339
|
-
text: ptr::null_mut(),
|
|
340
|
-
value_type: YerbaValueType::Null,
|
|
341
|
-
},
|
|
342
|
-
list: YerbaTypedList {
|
|
343
|
-
json: ptr::null_mut(),
|
|
344
|
-
length: 0,
|
|
345
|
-
},
|
|
346
|
-
location,
|
|
347
|
-
key_name: key_name_pointer,
|
|
348
|
-
key_location,
|
|
349
|
-
error: ptr::null_mut(),
|
|
350
|
-
}
|
|
351
|
-
}
|
|
263
|
+
match info.value {
|
|
264
|
+
Some(scalar) => base.scalar(&scalar.text, detect_yaml_type(&scalar)),
|
|
265
|
+
None => base.with_node_type(info.node_type),
|
|
352
266
|
}
|
|
353
267
|
}
|
|
354
268
|
}
|
|
355
269
|
|
|
270
|
+
fn location_to_ffi(location: crate::Location) -> YerbaLocation {
|
|
271
|
+
YerbaLocation {
|
|
272
|
+
start_offset: location.start_offset,
|
|
273
|
+
end_offset: location.end_offset,
|
|
274
|
+
start_line: location.start_line,
|
|
275
|
+
start_column: location.start_column,
|
|
276
|
+
end_line: location.end_line,
|
|
277
|
+
end_column: location.end_column,
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
356
281
|
/// Caller must free with yerba_string_free.
|
|
357
282
|
#[no_mangle]
|
|
358
283
|
pub unsafe extern "C" fn yerba_document_get_value(document: *const Document, path: *const c_char) -> *mut c_char {
|
|
359
284
|
let document = &*document;
|
|
360
|
-
let
|
|
285
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
361
286
|
|
|
362
|
-
match document.get_value(
|
|
287
|
+
match document.get_value(selector_string) {
|
|
363
288
|
Some(value) => {
|
|
364
289
|
let json = crate::json::yaml_to_json(&value);
|
|
365
290
|
let json_string = serde_json::to_string(&json).unwrap_or_else(|_| "null".to_string());
|
|
291
|
+
|
|
366
292
|
CString::new(json_string).unwrap_or_default().into_raw()
|
|
367
293
|
}
|
|
294
|
+
|
|
368
295
|
None => ptr::null_mut(),
|
|
369
296
|
}
|
|
370
297
|
}
|
|
@@ -373,9 +300,9 @@ pub unsafe extern "C" fn yerba_document_get_value(document: *const Document, pat
|
|
|
373
300
|
#[no_mangle]
|
|
374
301
|
pub unsafe extern "C" fn yerba_document_get_values(document: *const Document, path: *const c_char) -> *mut c_char {
|
|
375
302
|
let document = &*document;
|
|
376
|
-
let
|
|
303
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
377
304
|
|
|
378
|
-
let values = document.get_values(
|
|
305
|
+
let values = document.get_values(selector_string);
|
|
379
306
|
let json_values: Vec<serde_json::Value> = values.iter().map(crate::json::yaml_to_json).collect();
|
|
380
307
|
let json_string = serde_json::to_string(&json_values).unwrap_or_else(|_| "[]".to_string());
|
|
381
308
|
|
|
@@ -383,50 +310,40 @@ pub unsafe extern "C" fn yerba_document_get_values(document: *const Document, pa
|
|
|
383
310
|
}
|
|
384
311
|
|
|
385
312
|
#[no_mangle]
|
|
386
|
-
pub unsafe extern "C" fn yerba_document_get_quote_style(document: *const Document, path: *const c_char) ->
|
|
313
|
+
pub unsafe extern "C" fn yerba_document_get_quote_style(document: *const Document, path: *const c_char) -> *mut c_char {
|
|
387
314
|
let document = &*document;
|
|
388
|
-
let
|
|
389
|
-
|
|
390
|
-
match document.
|
|
391
|
-
Some(
|
|
392
|
-
|
|
393
|
-
SyntaxKind::SINGLE_QUOTED_SCALAR => 1,
|
|
394
|
-
SyntaxKind::DOUBLE_QUOTED_SCALAR => 2,
|
|
395
|
-
_ => -1,
|
|
396
|
-
},
|
|
315
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
316
|
+
|
|
317
|
+
match document.get_quote_style(selector_string) {
|
|
318
|
+
Some(style) => {
|
|
319
|
+
let ruby_style = style.replace('-', "_");
|
|
397
320
|
|
|
398
|
-
|
|
321
|
+
CString::new(ruby_style).map(|s| s.into_raw()).unwrap_or(std::ptr::null_mut())
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
None => std::ptr::null_mut(),
|
|
399
325
|
}
|
|
400
326
|
}
|
|
401
327
|
|
|
402
328
|
#[no_mangle]
|
|
403
|
-
pub unsafe extern "C" fn yerba_document_set_quote_style(
|
|
404
|
-
document: *mut Document,
|
|
405
|
-
path: *const c_char,
|
|
406
|
-
style: i32,
|
|
407
|
-
) -> YerbaResult {
|
|
329
|
+
pub unsafe extern "C" fn yerba_document_set_quote_style(document: *mut Document, path: *const c_char, style: *const c_char) -> YerbaResult {
|
|
408
330
|
let document = &mut *document;
|
|
409
|
-
let
|
|
331
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
332
|
+
let style_string = &CStr::from_ptr(style).to_str().unwrap_or("").replace('_', "-");
|
|
410
333
|
|
|
411
|
-
let quote_style = match
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
2 => QuoteStyle::Double,
|
|
415
|
-
_ => return YerbaResult::err("Invalid quote style (use 0=plain, 1=single, 2=double)"),
|
|
334
|
+
let quote_style = match style_string.parse::<QuoteStyle>() {
|
|
335
|
+
Ok(style) => style,
|
|
336
|
+
Err(e) => return YerbaResult::err(&e),
|
|
416
337
|
};
|
|
417
338
|
|
|
418
|
-
match document.
|
|
419
|
-
Ok(
|
|
339
|
+
match document.enforce_quotes_at("e_style, Some(selector_string)) {
|
|
340
|
+
Ok(_warnings) => YerbaResult::ok(),
|
|
420
341
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
421
342
|
}
|
|
422
343
|
}
|
|
423
344
|
|
|
424
345
|
#[no_mangle]
|
|
425
|
-
pub unsafe extern "C" fn yerba_document_evaluate_condition(
|
|
426
|
-
document: *const Document,
|
|
427
|
-
parent_path: *const c_char,
|
|
428
|
-
condition: *const c_char,
|
|
429
|
-
) -> bool {
|
|
346
|
+
pub unsafe extern "C" fn yerba_document_evaluate_condition(document: *const Document, parent_path: *const c_char, condition: *const c_char) -> bool {
|
|
430
347
|
let document = &*document;
|
|
431
348
|
let parent = CStr::from_ptr(parent_path).to_str().unwrap_or("");
|
|
432
349
|
let cond = CStr::from_ptr(condition).to_str().unwrap_or("");
|
|
@@ -436,62 +353,22 @@ pub unsafe extern "C" fn yerba_document_evaluate_condition(
|
|
|
436
353
|
#[no_mangle]
|
|
437
354
|
pub unsafe extern "C" fn yerba_document_exists(document: *const Document, path: *const c_char) -> bool {
|
|
438
355
|
let document = &*document;
|
|
439
|
-
let
|
|
440
|
-
document.exists(
|
|
356
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
357
|
+
document.exists(selector_string)
|
|
441
358
|
}
|
|
442
359
|
|
|
443
360
|
#[no_mangle]
|
|
444
|
-
pub unsafe extern "C" fn yerba_document_find(
|
|
445
|
-
document: *const Document,
|
|
446
|
-
path: *const c_char,
|
|
447
|
-
condition: *const c_char,
|
|
448
|
-
select: *const c_char,
|
|
449
|
-
) -> *mut c_char {
|
|
361
|
+
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 {
|
|
450
362
|
let document = &*document;
|
|
451
|
-
let
|
|
452
|
-
|
|
453
|
-
let condition_str = if condition.is_null() {
|
|
454
|
-
None
|
|
455
|
-
} else {
|
|
456
|
-
CStr::from_ptr(condition).to_str().ok()
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
let _select_string = if select.is_null() {
|
|
460
|
-
None
|
|
461
|
-
} else {
|
|
462
|
-
CStr::from_ptr(select).to_str().ok()
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
let values = match condition_str {
|
|
466
|
-
Some(cond) => document.filter(path_string, cond),
|
|
467
|
-
None => document.get_values(path_string),
|
|
468
|
-
};
|
|
469
|
-
|
|
470
|
-
let select_fields: Option<Vec<&str>> = _select_string.map(|s| s.split(',').collect());
|
|
471
|
-
|
|
472
|
-
let mut results: Vec<serde_json::Value> = Vec::new();
|
|
473
|
-
|
|
474
|
-
for value in &values {
|
|
475
|
-
match &select_fields {
|
|
476
|
-
Some(fields) => {
|
|
477
|
-
let mut result = serde_json::Map::new();
|
|
363
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
478
364
|
|
|
479
|
-
|
|
480
|
-
let json_value = crate::json::resolve_select_field(value, field);
|
|
481
|
-
let json_key = crate::json::select_field_key(field);
|
|
365
|
+
let condition_string = if condition.is_null() { None } else { CStr::from_ptr(condition).to_str().ok() };
|
|
482
366
|
|
|
483
|
-
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
results.push(serde_json::Value::Object(result));
|
|
487
|
-
}
|
|
488
|
-
None => {
|
|
489
|
-
results.push(crate::json::yaml_to_json(value));
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
367
|
+
let select_string = if select.is_null() { None } else { CStr::from_ptr(select).to_str().ok() };
|
|
493
368
|
|
|
369
|
+
let results = document.find_items(selector_string, condition_string, select_string);
|
|
494
370
|
let json = serde_json::to_string_pretty(&results).unwrap_or_else(|_| "[]".to_string());
|
|
371
|
+
|
|
495
372
|
CString::new(json).unwrap_or_default().into_raw()
|
|
496
373
|
}
|
|
497
374
|
|
|
@@ -501,14 +378,19 @@ pub unsafe extern "C" fn yerba_document_set(
|
|
|
501
378
|
path: *const c_char,
|
|
502
379
|
value: *const c_char,
|
|
503
380
|
value_type: YerbaValueType,
|
|
381
|
+
all: bool,
|
|
504
382
|
) -> YerbaResult {
|
|
505
383
|
let document = &mut *document;
|
|
506
|
-
let
|
|
384
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
507
385
|
let value_string = CStr::from_ptr(value).to_str().unwrap_or("");
|
|
508
386
|
|
|
509
|
-
let result =
|
|
510
|
-
|
|
511
|
-
|
|
387
|
+
let result = if all {
|
|
388
|
+
document.set_all(selector_string, value_string)
|
|
389
|
+
} else {
|
|
390
|
+
match value_type {
|
|
391
|
+
YerbaValueType::String => document.set(selector_string, value_string),
|
|
392
|
+
_ => document.set_plain(selector_string, value_string),
|
|
393
|
+
}
|
|
512
394
|
};
|
|
513
395
|
|
|
514
396
|
match result {
|
|
@@ -527,7 +409,7 @@ pub unsafe extern "C" fn yerba_document_insert(
|
|
|
527
409
|
at: i64,
|
|
528
410
|
) -> YerbaResult {
|
|
529
411
|
let document = &mut *document;
|
|
530
|
-
let
|
|
412
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
531
413
|
let value_string = CStr::from_ptr(value).to_str().unwrap_or("");
|
|
532
414
|
|
|
533
415
|
let position = if at >= 0 {
|
|
@@ -542,7 +424,7 @@ pub unsafe extern "C" fn yerba_document_insert(
|
|
|
542
424
|
InsertPosition::Last
|
|
543
425
|
};
|
|
544
426
|
|
|
545
|
-
match document.insert_into(
|
|
427
|
+
match document.insert_into(selector_string, value_string, position) {
|
|
546
428
|
Ok(()) => YerbaResult::ok(),
|
|
547
429
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
548
430
|
}
|
|
@@ -558,60 +440,14 @@ pub unsafe extern "C" fn yerba_document_insert_object(
|
|
|
558
440
|
at: i64,
|
|
559
441
|
) -> YerbaResult {
|
|
560
442
|
let document = &mut *document;
|
|
561
|
-
let
|
|
443
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
562
444
|
let json_string = CStr::from_ptr(json).to_str().unwrap_or("");
|
|
563
445
|
|
|
564
446
|
let json_value: serde_json::Value = match serde_json::from_str(json_string) {
|
|
565
|
-
Ok(
|
|
447
|
+
Ok(value) => value,
|
|
566
448
|
Err(e) => return YerbaResult::err(&format!("Invalid JSON: {}", e)),
|
|
567
449
|
};
|
|
568
450
|
|
|
569
|
-
let try_paths = if path_string.is_empty() {
|
|
570
|
-
vec!["[]".to_string(), "[0]".to_string()]
|
|
571
|
-
} else {
|
|
572
|
-
vec![format!("{}[]", path_string), format!("{}[0]", path_string)]
|
|
573
|
-
};
|
|
574
|
-
|
|
575
|
-
let mut quote_style = QuoteStyle::Plain;
|
|
576
|
-
|
|
577
|
-
'outer: for try_path in &try_paths {
|
|
578
|
-
for scalar in document.get_all_typed(try_path) {
|
|
579
|
-
if scalar.kind == SyntaxKind::DOUBLE_QUOTED_SCALAR {
|
|
580
|
-
quote_style = QuoteStyle::Double;
|
|
581
|
-
break 'outer;
|
|
582
|
-
} else if scalar.kind == SyntaxKind::SINGLE_QUOTED_SCALAR {
|
|
583
|
-
quote_style = QuoteStyle::Single;
|
|
584
|
-
break 'outer;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
if quote_style == QuoteStyle::Plain {
|
|
590
|
-
if let Some(serde_yaml::Value::Sequence(seq)) = document.get_value(path_string).as_ref() {
|
|
591
|
-
if let Some(serde_yaml::Value::Mapping(map)) = seq.first() {
|
|
592
|
-
if let Some((serde_yaml::Value::String(key_name), _)) = map.iter().next() {
|
|
593
|
-
let deep_path = if path_string.is_empty() {
|
|
594
|
-
format!("[].{}", key_name)
|
|
595
|
-
} else {
|
|
596
|
-
format!("{}[].{}", path_string, key_name)
|
|
597
|
-
};
|
|
598
|
-
|
|
599
|
-
for scalar in document.get_all_typed(&deep_path) {
|
|
600
|
-
if scalar.kind == SyntaxKind::DOUBLE_QUOTED_SCALAR {
|
|
601
|
-
quote_style = QuoteStyle::Double;
|
|
602
|
-
break;
|
|
603
|
-
} else if scalar.kind == SyntaxKind::SINGLE_QUOTED_SCALAR {
|
|
604
|
-
quote_style = QuoteStyle::Single;
|
|
605
|
-
break;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
let yaml_text = crate::yaml_writer::json_to_yaml_text(&json_value, "e_style, 0);
|
|
614
|
-
|
|
615
451
|
let position = if at >= 0 {
|
|
616
452
|
InsertPosition::At(at as usize)
|
|
617
453
|
} else if !before.is_null() {
|
|
@@ -624,7 +460,7 @@ pub unsafe extern "C" fn yerba_document_insert_object(
|
|
|
624
460
|
InsertPosition::Last
|
|
625
461
|
};
|
|
626
462
|
|
|
627
|
-
match document.
|
|
463
|
+
match document.insert_object(selector_string, &json_value, position) {
|
|
628
464
|
Ok(()) => YerbaResult::ok(),
|
|
629
465
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
630
466
|
}
|
|
@@ -633,51 +469,50 @@ pub unsafe extern "C" fn yerba_document_insert_object(
|
|
|
633
469
|
#[no_mangle]
|
|
634
470
|
pub unsafe extern "C" fn yerba_document_delete(document: *mut Document, path: *const c_char) -> YerbaResult {
|
|
635
471
|
let document = &mut *document;
|
|
636
|
-
let
|
|
472
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
637
473
|
|
|
638
|
-
match document.delete(
|
|
474
|
+
match document.delete(selector_string) {
|
|
639
475
|
Ok(()) => YerbaResult::ok(),
|
|
640
476
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
641
477
|
}
|
|
642
478
|
}
|
|
643
479
|
|
|
644
480
|
#[no_mangle]
|
|
645
|
-
pub unsafe extern "C" fn yerba_document_remove(
|
|
646
|
-
document: *mut Document,
|
|
647
|
-
path: *const c_char,
|
|
648
|
-
value: *const c_char,
|
|
649
|
-
) -> YerbaResult {
|
|
481
|
+
pub unsafe extern "C" fn yerba_document_remove(document: *mut Document, path: *const c_char, value: *const c_char) -> YerbaResult {
|
|
650
482
|
let document = &mut *document;
|
|
651
|
-
let
|
|
483
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
652
484
|
let value_string = CStr::from_ptr(value).to_str().unwrap_or("");
|
|
653
485
|
|
|
654
|
-
match document.remove(
|
|
486
|
+
match document.remove(selector_string, value_string) {
|
|
655
487
|
Ok(()) => YerbaResult::ok(),
|
|
656
488
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
657
489
|
}
|
|
658
490
|
}
|
|
659
491
|
|
|
660
492
|
#[no_mangle]
|
|
661
|
-
pub unsafe extern "C" fn yerba_document_remove_at(
|
|
662
|
-
document: *mut Document,
|
|
663
|
-
path: *const c_char,
|
|
664
|
-
index: usize,
|
|
665
|
-
) -> YerbaResult {
|
|
493
|
+
pub unsafe extern "C" fn yerba_document_remove_at(document: *mut Document, path: *const c_char, index: usize) -> YerbaResult {
|
|
666
494
|
let document = &mut *document;
|
|
667
|
-
let
|
|
495
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
668
496
|
|
|
669
|
-
match document.remove_at(
|
|
497
|
+
match document.remove_at(selector_string, index) {
|
|
670
498
|
Ok(()) => YerbaResult::ok(),
|
|
671
499
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
672
500
|
}
|
|
673
501
|
}
|
|
674
502
|
|
|
675
503
|
#[no_mangle]
|
|
676
|
-
pub unsafe extern "C" fn
|
|
677
|
-
document
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
504
|
+
pub unsafe extern "C" fn yerba_document_move_item(document: *mut Document, path: *const c_char, from: usize, to: usize) -> YerbaResult {
|
|
505
|
+
let document = &mut *document;
|
|
506
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
507
|
+
|
|
508
|
+
match document.move_item(selector_string, from, to) {
|
|
509
|
+
Ok(()) => YerbaResult::ok(),
|
|
510
|
+
Err(e) => YerbaResult::err(&e.to_string()),
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
#[no_mangle]
|
|
515
|
+
pub unsafe extern "C" fn yerba_document_rename(document: *mut Document, source: *const c_char, dest: *const c_char) -> YerbaResult {
|
|
681
516
|
let document = &mut *document;
|
|
682
517
|
let source_string = CStr::from_ptr(source).to_str().unwrap_or("");
|
|
683
518
|
let dest_string = CStr::from_ptr(dest).to_str().unwrap_or("");
|
|
@@ -689,59 +524,46 @@ pub unsafe extern "C" fn yerba_document_rename(
|
|
|
689
524
|
}
|
|
690
525
|
|
|
691
526
|
#[no_mangle]
|
|
692
|
-
pub unsafe extern "C" fn yerba_document_sort(
|
|
693
|
-
document: *mut Document,
|
|
694
|
-
path: *const c_char,
|
|
695
|
-
by: *const c_char,
|
|
696
|
-
case_sensitive: bool,
|
|
697
|
-
) -> YerbaResult {
|
|
527
|
+
pub unsafe extern "C" fn yerba_document_sort(document: *mut Document, path: *const c_char, by: *const c_char, case_sensitive: bool) -> YerbaResult {
|
|
698
528
|
let document = &mut *document;
|
|
699
|
-
let
|
|
529
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
700
530
|
|
|
701
|
-
let by_string = if by.is_null() {
|
|
702
|
-
None
|
|
703
|
-
} else {
|
|
704
|
-
CStr::from_ptr(by).to_str().ok()
|
|
705
|
-
};
|
|
531
|
+
let by_string = if by.is_null() { None } else { CStr::from_ptr(by).to_str().ok() };
|
|
706
532
|
|
|
707
533
|
let sort_fields: Vec<crate::SortField> = match by_string {
|
|
708
|
-
Some(fields) => fields
|
|
709
|
-
.split(',')
|
|
710
|
-
.map(|field| {
|
|
711
|
-
if let Some(name) = field.strip_suffix(":desc") {
|
|
712
|
-
crate::SortField {
|
|
713
|
-
path: name.to_string(),
|
|
714
|
-
ascending: false,
|
|
715
|
-
}
|
|
716
|
-
} else {
|
|
717
|
-
crate::SortField {
|
|
718
|
-
path: field.to_string(),
|
|
719
|
-
ascending: true,
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
})
|
|
723
|
-
.collect(),
|
|
534
|
+
Some(fields) => crate::SortField::parse_list(fields),
|
|
724
535
|
None => vec![],
|
|
725
536
|
};
|
|
726
537
|
|
|
727
|
-
match document.sort_items(
|
|
538
|
+
match document.sort_items(selector_string, &sort_fields, case_sensitive) {
|
|
728
539
|
Ok(()) => YerbaResult::ok(),
|
|
729
540
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
730
541
|
}
|
|
731
542
|
}
|
|
732
543
|
|
|
733
544
|
#[no_mangle]
|
|
734
|
-
pub unsafe extern "C" fn
|
|
735
|
-
document: *mut Document,
|
|
736
|
-
path: *const c_char,
|
|
737
|
-
order: *const c_char,
|
|
738
|
-
) -> YerbaResult {
|
|
545
|
+
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 {
|
|
739
546
|
let document = &mut *document;
|
|
740
|
-
let
|
|
547
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
548
|
+
let by_string = CStr::from_ptr(by).to_str().unwrap_or("");
|
|
549
|
+
let order_string = CStr::from_ptr(order_csv).to_str().unwrap_or("");
|
|
550
|
+
|
|
551
|
+
let desired_order: Vec<&str> = order_string.split(',').map(|s| s.trim()).collect();
|
|
552
|
+
|
|
553
|
+
match document.reorder_items(selector_string, by_string, &desired_order) {
|
|
554
|
+
Ok(()) => YerbaResult::ok(),
|
|
555
|
+
Err(e) => YerbaResult::err(&e.to_string()),
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
#[no_mangle]
|
|
560
|
+
pub unsafe extern "C" fn yerba_document_sort_keys(document: *mut Document, path: *const c_char, order: *const c_char) -> YerbaResult {
|
|
561
|
+
let document = &mut *document;
|
|
562
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
741
563
|
let order_string = CStr::from_ptr(order).to_str().unwrap_or("");
|
|
742
564
|
let key_order: Vec<&str> = order_string.split(',').collect();
|
|
743
565
|
|
|
744
|
-
match document.sort_keys(
|
|
566
|
+
match document.sort_keys(selector_string, &key_order) {
|
|
745
567
|
Ok(()) => YerbaResult::ok(),
|
|
746
568
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
747
569
|
}
|
|
@@ -756,55 +578,32 @@ pub unsafe extern "C" fn yerba_document_quote_style(
|
|
|
756
578
|
) -> YerbaResult {
|
|
757
579
|
let document = &mut *document;
|
|
758
580
|
|
|
759
|
-
let
|
|
760
|
-
None
|
|
761
|
-
} else {
|
|
762
|
-
CStr::from_ptr(path).to_str().ok()
|
|
763
|
-
};
|
|
581
|
+
let selector = if path.is_null() { None } else { CStr::from_ptr(path).to_str().ok() };
|
|
764
582
|
|
|
765
|
-
let
|
|
583
|
+
let key = if key_style.is_null() {
|
|
766
584
|
None
|
|
767
585
|
} else {
|
|
768
|
-
CStr::from_ptr(key_style)
|
|
769
|
-
.to_str()
|
|
770
|
-
.ok()
|
|
771
|
-
.and_then(|s| s.parse::<QuoteStyle>().ok())
|
|
586
|
+
CStr::from_ptr(key_style).to_str().ok().and_then(|s| s.parse::<crate::KeyStyle>().ok())
|
|
772
587
|
};
|
|
773
588
|
|
|
774
|
-
let
|
|
589
|
+
let value = if value_style.is_null() {
|
|
775
590
|
None
|
|
776
591
|
} else {
|
|
777
|
-
CStr::from_ptr(value_style)
|
|
778
|
-
.to_str()
|
|
779
|
-
.ok()
|
|
780
|
-
.and_then(|s| s.parse::<QuoteStyle>().ok())
|
|
592
|
+
CStr::from_ptr(value_style).to_str().ok().and_then(|s| s.parse::<QuoteStyle>().ok())
|
|
781
593
|
};
|
|
782
594
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
if let Some(ref value_style) = value_quote_style {
|
|
790
|
-
if let Err(e) = document.enforce_quotes_at(value_style, path_string) {
|
|
791
|
-
return YerbaResult::err(&e.to_string());
|
|
792
|
-
}
|
|
595
|
+
match document.enforce_quote_style(key.as_ref(), value.as_ref(), selector) {
|
|
596
|
+
Ok(()) => YerbaResult::ok(),
|
|
597
|
+
Err(e) => YerbaResult::err(&e.to_string()),
|
|
793
598
|
}
|
|
794
|
-
|
|
795
|
-
YerbaResult::ok()
|
|
796
599
|
}
|
|
797
600
|
|
|
798
601
|
#[no_mangle]
|
|
799
|
-
pub unsafe extern "C" fn yerba_document_blank_lines(
|
|
800
|
-
document: *mut Document,
|
|
801
|
-
path: *const c_char,
|
|
802
|
-
count: usize,
|
|
803
|
-
) -> YerbaResult {
|
|
602
|
+
pub unsafe extern "C" fn yerba_document_blank_lines(document: *mut Document, path: *const c_char, count: usize) -> YerbaResult {
|
|
804
603
|
let document = &mut *document;
|
|
805
|
-
let
|
|
604
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
806
605
|
|
|
807
|
-
match document.enforce_blank_lines(
|
|
606
|
+
match document.enforce_blank_lines(selector_string, count) {
|
|
808
607
|
Ok(()) => YerbaResult::ok(),
|
|
809
608
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
810
609
|
}
|
|
@@ -850,42 +649,12 @@ pub unsafe extern "C" fn yerba_get_result_free(result: YerbaGetResult) {
|
|
|
850
649
|
#[no_mangle]
|
|
851
650
|
pub unsafe extern "C" fn yerba_glob_get(glob_pattern: *const c_char, path: *const c_char) -> YerbaTypedList {
|
|
852
651
|
let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
|
|
853
|
-
let
|
|
854
|
-
let
|
|
855
|
-
|
|
856
|
-
let files = match glob::glob(pattern) {
|
|
857
|
-
Ok(paths) => paths.filter_map(|p| p.ok()).collect::<Vec<_>>(),
|
|
858
|
-
Err(_) => {
|
|
859
|
-
return YerbaTypedList {
|
|
860
|
-
json: CString::new("[]").unwrap_or_default().into_raw(),
|
|
861
|
-
length: 0,
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
};
|
|
865
|
-
|
|
866
|
-
use rayon::prelude::*;
|
|
867
|
-
|
|
868
|
-
let results: Vec<serde_json::Value> = files
|
|
869
|
-
.par_iter()
|
|
870
|
-
.flat_map(|file| {
|
|
871
|
-
let mut file_results = Vec::new();
|
|
652
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
653
|
+
let scalars = crate::glob_get(pattern, selector_string);
|
|
872
654
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
let value_type = detect_yaml_type(&scalar);
|
|
877
|
-
|
|
878
|
-
file_results.push(serde_json::json!({"text": scalar.text, "type": value_type as u8}));
|
|
879
|
-
}
|
|
880
|
-
} else if let Some(scalar) = document.get_typed(path_string) {
|
|
881
|
-
let value_type = detect_yaml_type(&scalar);
|
|
882
|
-
|
|
883
|
-
file_results.push(serde_json::json!({"text": scalar.text, "type": value_type as u8}));
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
file_results
|
|
888
|
-
})
|
|
655
|
+
let results: Vec<serde_json::Value> = scalars
|
|
656
|
+
.iter()
|
|
657
|
+
.map(|scalar| serde_json::json!({"text": scalar.text, "type": detect_yaml_type(scalar) as u8}))
|
|
889
658
|
.collect();
|
|
890
659
|
|
|
891
660
|
let length = results.len();
|
|
@@ -898,89 +667,13 @@ pub unsafe extern "C" fn yerba_glob_get(glob_pattern: *const c_char, path: *cons
|
|
|
898
667
|
}
|
|
899
668
|
|
|
900
669
|
#[no_mangle]
|
|
901
|
-
pub unsafe extern "C" fn yerba_glob_find(
|
|
902
|
-
glob_pattern: *const c_char,
|
|
903
|
-
path: *const c_char,
|
|
904
|
-
condition: *const c_char,
|
|
905
|
-
select: *const c_char,
|
|
906
|
-
) -> YerbaTypedList {
|
|
670
|
+
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 {
|
|
907
671
|
let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
|
|
908
|
-
let
|
|
909
|
-
|
|
910
|
-
let
|
|
911
|
-
None
|
|
912
|
-
} else {
|
|
913
|
-
CStr::from_ptr(condition).to_str().ok()
|
|
914
|
-
};
|
|
915
|
-
|
|
916
|
-
let _select_string = if select.is_null() {
|
|
917
|
-
None
|
|
918
|
-
} else {
|
|
919
|
-
CStr::from_ptr(select).to_str().ok()
|
|
920
|
-
};
|
|
921
|
-
|
|
922
|
-
let files = match glob::glob(pattern) {
|
|
923
|
-
Ok(paths) => paths.filter_map(|p| p.ok()).collect::<Vec<_>>(),
|
|
924
|
-
Err(_) => {
|
|
925
|
-
return YerbaTypedList {
|
|
926
|
-
json: CString::new("[]").unwrap_or_default().into_raw(),
|
|
927
|
-
length: 0,
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
};
|
|
931
|
-
|
|
932
|
-
use rayon::prelude::*;
|
|
933
|
-
|
|
934
|
-
let select_fields: Option<Vec<&str>> = _select_string.map(|s| s.split(',').collect());
|
|
935
|
-
|
|
936
|
-
let all_results: Vec<serde_json::Value> = files
|
|
937
|
-
.par_iter()
|
|
938
|
-
.flat_map(|file| {
|
|
939
|
-
let mut file_results = Vec::new();
|
|
940
|
-
|
|
941
|
-
if let Ok(document) = Document::parse_file(file) {
|
|
942
|
-
let values = match condition_string {
|
|
943
|
-
Some(cond) => document.filter(path_string, cond),
|
|
944
|
-
None => document.get_values(path_string),
|
|
945
|
-
};
|
|
946
|
-
|
|
947
|
-
let file_string = file.to_string_lossy().to_string();
|
|
948
|
-
|
|
949
|
-
for value in &values {
|
|
950
|
-
let mut result = serde_json::Map::new();
|
|
951
|
-
result.insert("__file".to_string(), serde_json::Value::String(file_string.clone()));
|
|
952
|
-
|
|
953
|
-
match &select_fields {
|
|
954
|
-
Some(fields) => {
|
|
955
|
-
for field in fields {
|
|
956
|
-
let json_value = crate::json::resolve_select_field(value, field);
|
|
957
|
-
let json_key = crate::json::select_field_key(field);
|
|
958
|
-
result.insert(json_key, json_value);
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
None => {
|
|
963
|
-
if let serde_yaml::Value::Mapping(map) = value {
|
|
964
|
-
for (key, yaml_value) in map {
|
|
965
|
-
let json_key = match key {
|
|
966
|
-
serde_yaml::Value::String(string) => string.clone(),
|
|
967
|
-
_ => format!("{:?}", key),
|
|
968
|
-
};
|
|
969
|
-
|
|
970
|
-
result.insert(json_key, crate::json::yaml_to_json(yaml_value));
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
file_results.push(serde_json::Value::Object(result));
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
file_results
|
|
981
|
-
})
|
|
982
|
-
.collect();
|
|
672
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
673
|
+
let condition_string = if condition.is_null() { None } else { CStr::from_ptr(condition).to_str().ok() };
|
|
674
|
+
let select_string = if select.is_null() { None } else { CStr::from_ptr(select).to_str().ok() };
|
|
983
675
|
|
|
676
|
+
let all_results = crate::glob_find(pattern, selector_string, condition_string, select_string);
|
|
984
677
|
let length = all_results.len();
|
|
985
678
|
let json = serde_json::to_string_pretty(&all_results).unwrap_or_else(|_| "[]".to_string());
|
|
986
679
|
|