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.
- checksums.yaml +4 -4
- data/README.md +93 -8
- data/exe/aarch64-linux-gnu/yerba +0 -0
- data/ext/yerba/extconf.rb +22 -3
- data/ext/yerba/include/yerba.h +32 -9
- data/ext/yerba/yerba.c +133 -25
- data/lib/yerba/3.2/yerba.so +0 -0
- data/lib/yerba/3.3/yerba.so +0 -0
- data/lib/yerba/3.4/yerba.so +0 -0
- data/lib/yerba/4.0/yerba.so +0 -0
- data/lib/yerba/collection.rb +35 -0
- data/lib/yerba/document.rb +45 -3
- data/lib/yerba/query_result.rb +50 -0
- data/lib/yerba/sequence.rb +187 -1
- data/lib/yerba/version.rb +1 -1
- data/lib/yerba/yerbafile.rb +45 -0
- data/lib/yerba.rb +2 -0
- data/rust/Cargo.lock +3 -1
- data/rust/Cargo.toml +3 -2
- data/rust/cbindgen.toml +1 -0
- data/rust/rustfmt.toml +1 -1
- data/rust/src/commands/apply.rs +11 -2
- data/rust/src/commands/blank_lines.rs +1 -4
- data/rust/src/commands/check.rs +11 -2
- data/rust/src/commands/directives.rs +61 -0
- data/rust/src/commands/get.rs +5 -22
- data/rust/src/commands/mod.rs +16 -18
- data/rust/src/commands/quote_style.rs +12 -6
- data/rust/src/commands/selectors.rs +3 -19
- data/rust/src/commands/sort.rs +22 -157
- data/rust/src/didyoumean.rs +2 -4
- 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 +384 -0
- data/rust/src/document/mod.rs +784 -0
- data/rust/src/document/set.rs +100 -0
- data/rust/src/document/sort.rs +639 -0
- data/rust/src/document/style.rs +473 -0
- data/rust/src/error.rs +24 -6
- data/rust/src/ffi.rs +272 -518
- data/rust/src/json.rs +1 -7
- data/rust/src/lib.rs +88 -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 +86 -19
- metadata +13 -3
- data/rust/src/document.rs +0 -2304
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
|
-
|
|
237
|
-
BlockMapEntry::cast(parent).and_then(|entry| {
|
|
238
|
-
entry.key().and_then(|key_node| {
|
|
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));
|
|
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);
|
|
249
239
|
|
|
250
|
-
|
|
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.get_typed(path_string) {
|
|
391
|
-
Some(scalar) => match scalar.kind {
|
|
392
|
-
SyntaxKind::PLAIN_SCALAR => 0,
|
|
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("");
|
|
397
316
|
|
|
398
|
-
|
|
317
|
+
match document.get_quote_style(selector_string) {
|
|
318
|
+
Some(style) => {
|
|
319
|
+
let ruby_style = style.replace('-', "_");
|
|
320
|
+
|
|
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());
|
|
363
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
471
364
|
|
|
472
|
-
let
|
|
365
|
+
let condition_string = if condition.is_null() { None } else { CStr::from_ptr(condition).to_str().ok() };
|
|
473
366
|
|
|
474
|
-
|
|
475
|
-
match &select_fields {
|
|
476
|
-
Some(fields) => {
|
|
477
|
-
let mut result = serde_json::Map::new();
|
|
478
|
-
|
|
479
|
-
for field in fields {
|
|
480
|
-
let json_value = crate::json::resolve_select_field(value, field);
|
|
481
|
-
let json_key = crate::json::select_field_key(field);
|
|
482
|
-
|
|
483
|
-
result.insert(json_key, json_value);
|
|
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
|
|
|
@@ -504,15 +381,15 @@ pub unsafe extern "C" fn yerba_document_set(
|
|
|
504
381
|
all: bool,
|
|
505
382
|
) -> YerbaResult {
|
|
506
383
|
let document = &mut *document;
|
|
507
|
-
let
|
|
384
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
508
385
|
let value_string = CStr::from_ptr(value).to_str().unwrap_or("");
|
|
509
386
|
|
|
510
387
|
let result = if all {
|
|
511
|
-
document.set_all(
|
|
388
|
+
document.set_all(selector_string, value_string)
|
|
512
389
|
} else {
|
|
513
390
|
match value_type {
|
|
514
|
-
YerbaValueType::String => document.set(
|
|
515
|
-
_ => document.set_plain(
|
|
391
|
+
YerbaValueType::String => document.set(selector_string, value_string),
|
|
392
|
+
_ => document.set_plain(selector_string, value_string),
|
|
516
393
|
}
|
|
517
394
|
};
|
|
518
395
|
|
|
@@ -532,7 +409,7 @@ pub unsafe extern "C" fn yerba_document_insert(
|
|
|
532
409
|
at: i64,
|
|
533
410
|
) -> YerbaResult {
|
|
534
411
|
let document = &mut *document;
|
|
535
|
-
let
|
|
412
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
536
413
|
let value_string = CStr::from_ptr(value).to_str().unwrap_or("");
|
|
537
414
|
|
|
538
415
|
let position = if at >= 0 {
|
|
@@ -547,7 +424,7 @@ pub unsafe extern "C" fn yerba_document_insert(
|
|
|
547
424
|
InsertPosition::Last
|
|
548
425
|
};
|
|
549
426
|
|
|
550
|
-
match document.insert_into(
|
|
427
|
+
match document.insert_into(selector_string, value_string, position) {
|
|
551
428
|
Ok(()) => YerbaResult::ok(),
|
|
552
429
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
553
430
|
}
|
|
@@ -563,60 +440,14 @@ pub unsafe extern "C" fn yerba_document_insert_object(
|
|
|
563
440
|
at: i64,
|
|
564
441
|
) -> YerbaResult {
|
|
565
442
|
let document = &mut *document;
|
|
566
|
-
let
|
|
443
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
567
444
|
let json_string = CStr::from_ptr(json).to_str().unwrap_or("");
|
|
568
445
|
|
|
569
446
|
let json_value: serde_json::Value = match serde_json::from_str(json_string) {
|
|
570
|
-
Ok(
|
|
447
|
+
Ok(value) => value,
|
|
571
448
|
Err(e) => return YerbaResult::err(&format!("Invalid JSON: {}", e)),
|
|
572
449
|
};
|
|
573
450
|
|
|
574
|
-
let try_paths = if path_string.is_empty() {
|
|
575
|
-
vec!["[]".to_string(), "[0]".to_string()]
|
|
576
|
-
} else {
|
|
577
|
-
vec![format!("{}[]", path_string), format!("{}[0]", path_string)]
|
|
578
|
-
};
|
|
579
|
-
|
|
580
|
-
let mut quote_style = QuoteStyle::Plain;
|
|
581
|
-
|
|
582
|
-
'outer: for try_path in &try_paths {
|
|
583
|
-
for scalar in document.get_all_typed(try_path) {
|
|
584
|
-
if scalar.kind == SyntaxKind::DOUBLE_QUOTED_SCALAR {
|
|
585
|
-
quote_style = QuoteStyle::Double;
|
|
586
|
-
break 'outer;
|
|
587
|
-
} else if scalar.kind == SyntaxKind::SINGLE_QUOTED_SCALAR {
|
|
588
|
-
quote_style = QuoteStyle::Single;
|
|
589
|
-
break 'outer;
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
if quote_style == QuoteStyle::Plain {
|
|
595
|
-
if let Some(serde_yaml::Value::Sequence(seq)) = document.get_value(path_string).as_ref() {
|
|
596
|
-
if let Some(serde_yaml::Value::Mapping(map)) = seq.first() {
|
|
597
|
-
if let Some((serde_yaml::Value::String(key_name), _)) = map.iter().next() {
|
|
598
|
-
let deep_path = if path_string.is_empty() {
|
|
599
|
-
format!("[].{}", key_name)
|
|
600
|
-
} else {
|
|
601
|
-
format!("{}[].{}", path_string, key_name)
|
|
602
|
-
};
|
|
603
|
-
|
|
604
|
-
for scalar in document.get_all_typed(&deep_path) {
|
|
605
|
-
if scalar.kind == SyntaxKind::DOUBLE_QUOTED_SCALAR {
|
|
606
|
-
quote_style = QuoteStyle::Double;
|
|
607
|
-
break;
|
|
608
|
-
} else if scalar.kind == SyntaxKind::SINGLE_QUOTED_SCALAR {
|
|
609
|
-
quote_style = QuoteStyle::Single;
|
|
610
|
-
break;
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
let yaml_text = crate::yaml_writer::json_to_yaml_text(&json_value, "e_style, 0);
|
|
619
|
-
|
|
620
451
|
let position = if at >= 0 {
|
|
621
452
|
InsertPosition::At(at as usize)
|
|
622
453
|
} else if !before.is_null() {
|
|
@@ -629,7 +460,7 @@ pub unsafe extern "C" fn yerba_document_insert_object(
|
|
|
629
460
|
InsertPosition::Last
|
|
630
461
|
};
|
|
631
462
|
|
|
632
|
-
match document.
|
|
463
|
+
match document.insert_object(selector_string, &json_value, position) {
|
|
633
464
|
Ok(()) => YerbaResult::ok(),
|
|
634
465
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
635
466
|
}
|
|
@@ -638,51 +469,67 @@ pub unsafe extern "C" fn yerba_document_insert_object(
|
|
|
638
469
|
#[no_mangle]
|
|
639
470
|
pub unsafe extern "C" fn yerba_document_delete(document: *mut Document, path: *const c_char) -> YerbaResult {
|
|
640
471
|
let document = &mut *document;
|
|
641
|
-
let
|
|
472
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
642
473
|
|
|
643
|
-
match document.delete(
|
|
474
|
+
match document.delete(selector_string) {
|
|
644
475
|
Ok(()) => YerbaResult::ok(),
|
|
645
476
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
646
477
|
}
|
|
647
478
|
}
|
|
648
479
|
|
|
649
480
|
#[no_mangle]
|
|
650
|
-
pub unsafe extern "C" fn
|
|
651
|
-
document: *mut Document,
|
|
652
|
-
path: *const c_char,
|
|
653
|
-
value: *const c_char,
|
|
654
|
-
) -> YerbaResult {
|
|
481
|
+
pub unsafe extern "C" fn yerba_document_insert_objects(document: *mut Document, path: *const c_char, json: *const c_char) -> YerbaResult {
|
|
655
482
|
let document = &mut *document;
|
|
656
|
-
let
|
|
483
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
484
|
+
let json_string = CStr::from_ptr(json).to_str().unwrap_or("");
|
|
485
|
+
|
|
486
|
+
let json_values: Vec<serde_json::Value> = match serde_json::from_str(json_string) {
|
|
487
|
+
Ok(values) => values,
|
|
488
|
+
Err(e) => return YerbaResult::err(&format!("Invalid JSON: {}", e)),
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
match document.insert_objects(selector_string, &json_values) {
|
|
492
|
+
Ok(()) => YerbaResult::ok(),
|
|
493
|
+
Err(e) => YerbaResult::err(&e.to_string()),
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
#[no_mangle]
|
|
498
|
+
pub unsafe extern "C" fn yerba_document_remove(document: *mut Document, path: *const c_char, value: *const c_char) -> YerbaResult {
|
|
499
|
+
let document = &mut *document;
|
|
500
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
657
501
|
let value_string = CStr::from_ptr(value).to_str().unwrap_or("");
|
|
658
502
|
|
|
659
|
-
match document.remove(
|
|
503
|
+
match document.remove(selector_string, value_string) {
|
|
660
504
|
Ok(()) => YerbaResult::ok(),
|
|
661
505
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
662
506
|
}
|
|
663
507
|
}
|
|
664
508
|
|
|
665
509
|
#[no_mangle]
|
|
666
|
-
pub unsafe extern "C" fn yerba_document_remove_at(
|
|
667
|
-
document: *mut Document,
|
|
668
|
-
path: *const c_char,
|
|
669
|
-
index: usize,
|
|
670
|
-
) -> YerbaResult {
|
|
510
|
+
pub unsafe extern "C" fn yerba_document_remove_at(document: *mut Document, path: *const c_char, index: usize) -> YerbaResult {
|
|
671
511
|
let document = &mut *document;
|
|
672
|
-
let
|
|
512
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
673
513
|
|
|
674
|
-
match document.remove_at(
|
|
514
|
+
match document.remove_at(selector_string, index) {
|
|
675
515
|
Ok(()) => YerbaResult::ok(),
|
|
676
516
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
677
517
|
}
|
|
678
518
|
}
|
|
679
519
|
|
|
680
520
|
#[no_mangle]
|
|
681
|
-
pub unsafe extern "C" fn
|
|
682
|
-
document
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
521
|
+
pub unsafe extern "C" fn yerba_document_move_item(document: *mut Document, path: *const c_char, from: usize, to: usize) -> YerbaResult {
|
|
522
|
+
let document = &mut *document;
|
|
523
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
524
|
+
|
|
525
|
+
match document.move_item(selector_string, from, to) {
|
|
526
|
+
Ok(()) => YerbaResult::ok(),
|
|
527
|
+
Err(e) => YerbaResult::err(&e.to_string()),
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
#[no_mangle]
|
|
532
|
+
pub unsafe extern "C" fn yerba_document_rename(document: *mut Document, source: *const c_char, dest: *const c_char) -> YerbaResult {
|
|
686
533
|
let document = &mut *document;
|
|
687
534
|
let source_string = CStr::from_ptr(source).to_str().unwrap_or("");
|
|
688
535
|
let dest_string = CStr::from_ptr(dest).to_str().unwrap_or("");
|
|
@@ -694,59 +541,46 @@ pub unsafe extern "C" fn yerba_document_rename(
|
|
|
694
541
|
}
|
|
695
542
|
|
|
696
543
|
#[no_mangle]
|
|
697
|
-
pub unsafe extern "C" fn yerba_document_sort(
|
|
698
|
-
document: *mut Document,
|
|
699
|
-
path: *const c_char,
|
|
700
|
-
by: *const c_char,
|
|
701
|
-
case_sensitive: bool,
|
|
702
|
-
) -> YerbaResult {
|
|
544
|
+
pub unsafe extern "C" fn yerba_document_sort(document: *mut Document, path: *const c_char, by: *const c_char, case_sensitive: bool) -> YerbaResult {
|
|
703
545
|
let document = &mut *document;
|
|
704
|
-
let
|
|
546
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
705
547
|
|
|
706
|
-
let by_string = if by.is_null() {
|
|
707
|
-
None
|
|
708
|
-
} else {
|
|
709
|
-
CStr::from_ptr(by).to_str().ok()
|
|
710
|
-
};
|
|
548
|
+
let by_string = if by.is_null() { None } else { CStr::from_ptr(by).to_str().ok() };
|
|
711
549
|
|
|
712
550
|
let sort_fields: Vec<crate::SortField> = match by_string {
|
|
713
|
-
Some(fields) => fields
|
|
714
|
-
.split(',')
|
|
715
|
-
.map(|field| {
|
|
716
|
-
if let Some(name) = field.strip_suffix(":desc") {
|
|
717
|
-
crate::SortField {
|
|
718
|
-
path: name.to_string(),
|
|
719
|
-
ascending: false,
|
|
720
|
-
}
|
|
721
|
-
} else {
|
|
722
|
-
crate::SortField {
|
|
723
|
-
path: field.to_string(),
|
|
724
|
-
ascending: true,
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
})
|
|
728
|
-
.collect(),
|
|
551
|
+
Some(fields) => crate::SortField::parse_list(fields),
|
|
729
552
|
None => vec![],
|
|
730
553
|
};
|
|
731
554
|
|
|
732
|
-
match document.sort_items(
|
|
555
|
+
match document.sort_items(selector_string, &sort_fields, case_sensitive) {
|
|
733
556
|
Ok(()) => YerbaResult::ok(),
|
|
734
557
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
735
558
|
}
|
|
736
559
|
}
|
|
737
560
|
|
|
738
561
|
#[no_mangle]
|
|
739
|
-
pub unsafe extern "C" fn
|
|
740
|
-
document: *mut Document,
|
|
741
|
-
path: *const c_char,
|
|
742
|
-
order: *const c_char,
|
|
743
|
-
) -> YerbaResult {
|
|
562
|
+
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 {
|
|
744
563
|
let document = &mut *document;
|
|
745
|
-
let
|
|
564
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
565
|
+
let by_string = CStr::from_ptr(by).to_str().unwrap_or("");
|
|
566
|
+
let order_string = CStr::from_ptr(order_csv).to_str().unwrap_or("");
|
|
567
|
+
|
|
568
|
+
let desired_order: Vec<&str> = order_string.split(',').map(|s| s.trim()).collect();
|
|
569
|
+
|
|
570
|
+
match document.reorder_items(selector_string, by_string, &desired_order) {
|
|
571
|
+
Ok(()) => YerbaResult::ok(),
|
|
572
|
+
Err(e) => YerbaResult::err(&e.to_string()),
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
#[no_mangle]
|
|
577
|
+
pub unsafe extern "C" fn yerba_document_sort_keys(document: *mut Document, path: *const c_char, order: *const c_char) -> YerbaResult {
|
|
578
|
+
let document = &mut *document;
|
|
579
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
746
580
|
let order_string = CStr::from_ptr(order).to_str().unwrap_or("");
|
|
747
581
|
let key_order: Vec<&str> = order_string.split(',').collect();
|
|
748
582
|
|
|
749
|
-
match document.sort_keys(
|
|
583
|
+
match document.sort_keys(selector_string, &key_order) {
|
|
750
584
|
Ok(()) => YerbaResult::ok(),
|
|
751
585
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
752
586
|
}
|
|
@@ -761,56 +595,82 @@ pub unsafe extern "C" fn yerba_document_quote_style(
|
|
|
761
595
|
) -> YerbaResult {
|
|
762
596
|
let document = &mut *document;
|
|
763
597
|
|
|
764
|
-
let
|
|
765
|
-
None
|
|
766
|
-
} else {
|
|
767
|
-
CStr::from_ptr(path).to_str().ok()
|
|
768
|
-
};
|
|
598
|
+
let selector = if path.is_null() { None } else { CStr::from_ptr(path).to_str().ok() };
|
|
769
599
|
|
|
770
|
-
let
|
|
600
|
+
let key = if key_style.is_null() {
|
|
771
601
|
None
|
|
772
602
|
} else {
|
|
773
|
-
CStr::from_ptr(key_style)
|
|
774
|
-
.to_str()
|
|
775
|
-
.ok()
|
|
776
|
-
.and_then(|s| s.parse::<QuoteStyle>().ok())
|
|
603
|
+
CStr::from_ptr(key_style).to_str().ok().and_then(|s| s.parse::<crate::KeyStyle>().ok())
|
|
777
604
|
};
|
|
778
605
|
|
|
779
|
-
let
|
|
606
|
+
let value = if value_style.is_null() {
|
|
780
607
|
None
|
|
781
608
|
} else {
|
|
782
|
-
CStr::from_ptr(value_style)
|
|
783
|
-
.to_str()
|
|
784
|
-
.ok()
|
|
785
|
-
.and_then(|s| s.parse::<QuoteStyle>().ok())
|
|
609
|
+
CStr::from_ptr(value_style).to_str().ok().and_then(|s| s.parse::<QuoteStyle>().ok())
|
|
786
610
|
};
|
|
787
611
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
}
|
|
612
|
+
match document.enforce_quote_style(key.as_ref(), value.as_ref(), selector) {
|
|
613
|
+
Ok(()) => YerbaResult::ok(),
|
|
614
|
+
Err(e) => YerbaResult::err(&e.to_string()),
|
|
792
615
|
}
|
|
616
|
+
}
|
|
793
617
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
618
|
+
#[no_mangle]
|
|
619
|
+
pub unsafe extern "C" fn yerba_document_blank_lines(document: *mut Document, path: *const c_char, count: usize) -> YerbaResult {
|
|
620
|
+
let document = &mut *document;
|
|
621
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
622
|
+
|
|
623
|
+
match document.enforce_blank_lines(selector_string, count) {
|
|
624
|
+
Ok(()) => YerbaResult::ok(),
|
|
625
|
+
Err(e) => YerbaResult::err(&e.to_string()),
|
|
798
626
|
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/// Caller must free with yerba_string_free.
|
|
630
|
+
#[no_mangle]
|
|
631
|
+
pub unsafe extern "C" fn yerba_yerbafile_find(directory: *const c_char) -> *mut c_char {
|
|
632
|
+
let start = if directory.is_null() {
|
|
633
|
+
std::env::current_dir().ok()
|
|
634
|
+
} else {
|
|
635
|
+
CStr::from_ptr(directory).to_str().ok().map(std::path::PathBuf::from)
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
let path = match start {
|
|
639
|
+
Some(dir) => crate::Yerbafile::find_from(dir),
|
|
640
|
+
None => None,
|
|
641
|
+
};
|
|
799
642
|
|
|
800
|
-
|
|
643
|
+
match path {
|
|
644
|
+
Some(path) => CString::new(path.to_string_lossy().to_string()).unwrap_or_default().into_raw(),
|
|
645
|
+
None => ptr::null_mut(),
|
|
646
|
+
}
|
|
801
647
|
}
|
|
802
648
|
|
|
803
649
|
#[no_mangle]
|
|
804
|
-
pub unsafe extern "C" fn
|
|
805
|
-
document: *mut Document,
|
|
806
|
-
path: *const c_char,
|
|
807
|
-
count: usize,
|
|
808
|
-
) -> YerbaResult {
|
|
650
|
+
pub unsafe extern "C" fn yerba_document_apply_yerbafile(document: *mut Document, file_path: *const c_char, yerbafile_path: *const c_char) -> YerbaResult {
|
|
809
651
|
let document = &mut *document;
|
|
810
|
-
let
|
|
652
|
+
let file_path_string = CStr::from_ptr(file_path).to_str().unwrap_or("");
|
|
811
653
|
|
|
812
|
-
|
|
813
|
-
|
|
654
|
+
let yerbafile = if yerbafile_path.is_null() {
|
|
655
|
+
match crate::Yerbafile::find() {
|
|
656
|
+
Some(path) => match crate::Yerbafile::load(&path) {
|
|
657
|
+
Ok(yerbafile) => yerbafile,
|
|
658
|
+
Err(e) => return YerbaResult::err(&e.to_string()),
|
|
659
|
+
},
|
|
660
|
+
|
|
661
|
+
None => return YerbaResult::err("No Yerbafile found"),
|
|
662
|
+
}
|
|
663
|
+
} else {
|
|
664
|
+
let path = CStr::from_ptr(yerbafile_path).to_str().unwrap_or("");
|
|
665
|
+
|
|
666
|
+
match crate::Yerbafile::load(path) {
|
|
667
|
+
Ok(yerbafile) => yerbafile,
|
|
668
|
+
Err(e) => return YerbaResult::err(&e.to_string()),
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
match yerbafile.apply_to_document(document, file_path_string) {
|
|
673
|
+
Ok(_) => YerbaResult::ok(),
|
|
814
674
|
Err(e) => YerbaResult::err(&e.to_string()),
|
|
815
675
|
}
|
|
816
676
|
}
|
|
@@ -855,42 +715,12 @@ pub unsafe extern "C" fn yerba_get_result_free(result: YerbaGetResult) {
|
|
|
855
715
|
#[no_mangle]
|
|
856
716
|
pub unsafe extern "C" fn yerba_glob_get(glob_pattern: *const c_char, path: *const c_char) -> YerbaTypedList {
|
|
857
717
|
let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
|
|
858
|
-
let
|
|
859
|
-
let
|
|
860
|
-
|
|
861
|
-
let files = match glob::glob(pattern) {
|
|
862
|
-
Ok(paths) => paths.filter_map(|p| p.ok()).collect::<Vec<_>>(),
|
|
863
|
-
Err(_) => {
|
|
864
|
-
return YerbaTypedList {
|
|
865
|
-
json: CString::new("[]").unwrap_or_default().into_raw(),
|
|
866
|
-
length: 0,
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
|
|
871
|
-
use rayon::prelude::*;
|
|
872
|
-
|
|
873
|
-
let results: Vec<serde_json::Value> = files
|
|
874
|
-
.par_iter()
|
|
875
|
-
.flat_map(|file| {
|
|
876
|
-
let mut file_results = Vec::new();
|
|
718
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
719
|
+
let scalars = crate::glob_get(pattern, selector_string);
|
|
877
720
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
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
|
-
} else if let Some(scalar) = document.get_typed(path_string) {
|
|
886
|
-
let value_type = detect_yaml_type(&scalar);
|
|
887
|
-
|
|
888
|
-
file_results.push(serde_json::json!({"text": scalar.text, "type": value_type as u8}));
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
file_results
|
|
893
|
-
})
|
|
721
|
+
let results: Vec<serde_json::Value> = scalars
|
|
722
|
+
.iter()
|
|
723
|
+
.map(|scalar| serde_json::json!({"text": scalar.text, "type": detect_yaml_type(scalar) as u8}))
|
|
894
724
|
.collect();
|
|
895
725
|
|
|
896
726
|
let length = results.len();
|
|
@@ -903,89 +733,13 @@ pub unsafe extern "C" fn yerba_glob_get(glob_pattern: *const c_char, path: *cons
|
|
|
903
733
|
}
|
|
904
734
|
|
|
905
735
|
#[no_mangle]
|
|
906
|
-
pub unsafe extern "C" fn yerba_glob_find(
|
|
907
|
-
glob_pattern: *const c_char,
|
|
908
|
-
path: *const c_char,
|
|
909
|
-
condition: *const c_char,
|
|
910
|
-
select: *const c_char,
|
|
911
|
-
) -> YerbaTypedList {
|
|
736
|
+
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 {
|
|
912
737
|
let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
|
|
913
|
-
let
|
|
914
|
-
|
|
915
|
-
let
|
|
916
|
-
None
|
|
917
|
-
} else {
|
|
918
|
-
CStr::from_ptr(condition).to_str().ok()
|
|
919
|
-
};
|
|
920
|
-
|
|
921
|
-
let _select_string = if select.is_null() {
|
|
922
|
-
None
|
|
923
|
-
} else {
|
|
924
|
-
CStr::from_ptr(select).to_str().ok()
|
|
925
|
-
};
|
|
926
|
-
|
|
927
|
-
let files = match glob::glob(pattern) {
|
|
928
|
-
Ok(paths) => paths.filter_map(|p| p.ok()).collect::<Vec<_>>(),
|
|
929
|
-
Err(_) => {
|
|
930
|
-
return YerbaTypedList {
|
|
931
|
-
json: CString::new("[]").unwrap_or_default().into_raw(),
|
|
932
|
-
length: 0,
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
};
|
|
936
|
-
|
|
937
|
-
use rayon::prelude::*;
|
|
938
|
-
|
|
939
|
-
let select_fields: Option<Vec<&str>> = _select_string.map(|s| s.split(',').collect());
|
|
940
|
-
|
|
941
|
-
let all_results: Vec<serde_json::Value> = files
|
|
942
|
-
.par_iter()
|
|
943
|
-
.flat_map(|file| {
|
|
944
|
-
let mut file_results = Vec::new();
|
|
945
|
-
|
|
946
|
-
if let Ok(document) = Document::parse_file(file) {
|
|
947
|
-
let values = match condition_string {
|
|
948
|
-
Some(cond) => document.filter(path_string, cond),
|
|
949
|
-
None => document.get_values(path_string),
|
|
950
|
-
};
|
|
951
|
-
|
|
952
|
-
let file_string = file.to_string_lossy().to_string();
|
|
953
|
-
|
|
954
|
-
for value in &values {
|
|
955
|
-
let mut result = serde_json::Map::new();
|
|
956
|
-
result.insert("__file".to_string(), serde_json::Value::String(file_string.clone()));
|
|
957
|
-
|
|
958
|
-
match &select_fields {
|
|
959
|
-
Some(fields) => {
|
|
960
|
-
for field in fields {
|
|
961
|
-
let json_value = crate::json::resolve_select_field(value, field);
|
|
962
|
-
let json_key = crate::json::select_field_key(field);
|
|
963
|
-
result.insert(json_key, json_value);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
None => {
|
|
968
|
-
if let serde_yaml::Value::Mapping(map) = value {
|
|
969
|
-
for (key, yaml_value) in map {
|
|
970
|
-
let json_key = match key {
|
|
971
|
-
serde_yaml::Value::String(string) => string.clone(),
|
|
972
|
-
_ => format!("{:?}", key),
|
|
973
|
-
};
|
|
974
|
-
|
|
975
|
-
result.insert(json_key, crate::json::yaml_to_json(yaml_value));
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
file_results.push(serde_json::Value::Object(result));
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
file_results
|
|
986
|
-
})
|
|
987
|
-
.collect();
|
|
738
|
+
let selector_string = CStr::from_ptr(path).to_str().unwrap_or("");
|
|
739
|
+
let condition_string = if condition.is_null() { None } else { CStr::from_ptr(condition).to_str().ok() };
|
|
740
|
+
let select_string = if select.is_null() { None } else { CStr::from_ptr(select).to_str().ok() };
|
|
988
741
|
|
|
742
|
+
let all_results = crate::glob_find(pattern, selector_string, condition_string, select_string);
|
|
989
743
|
let length = all_results.len();
|
|
990
744
|
let json = serde_json::to_string_pretty(&all_results).unwrap_or_else(|_| "[]".to_string());
|
|
991
745
|
|