1use toml::Value;
52use toml::value::Index;
53use std::ops::{Div, BitOr, Shl, ShlAssign, Not, Deref, DerefMut};
54
55fn path<'tr, B>(v: Option<&'tr Value>, p: B) -> Option<&'tr Value>
59where B: PathBuilder + Index + Copy
60{
61 if v.is_none() {
62 return None;
63 }
64
65 let v = v.unwrap();
66 let from_index = v.get(p);
67 if from_index.is_some() {
68 return from_index;
69 }
70
71 let path_segment = p.build_path();
72 if path_segment.paths.len() > 1 {
73 return path_segment.apply(v);
74 }
75
76 return None;
77}
78
79fn path_mut<'tr, B>(v: Option<&'tr mut Value>, p: B) -> Option<&'tr mut Value>
81where B: PathBuilder + Index + Copy
82{
83 if v.is_none() {
84 return None;
85 }
86
87 let v = v.unwrap();
88
89 let target = v.get(p);
92 if target.is_some() {
93 return v.get_mut(p);
94 }
95 else {
96 let path_segment = p.build_path();
97 if path_segment.paths.len() > 1 {
98 return path_segment.apply_mut(v);
99 }
100 else {
101 return None;
102 }
103 }
104}
105
106struct PathSegment
109{
110 paths: Vec<String>,
111}
112
113impl PathSegment
114{
115 fn apply<'tr>(&self, v: &'tr Value) -> Option<&'tr Value> {
117 let mut target = Some(v);
118 for p in &self.paths {
119 if target.is_none() {
120 return None;
121 }
122 if p.is_empty() {
123 continue;
124 }
125 match target.unwrap() {
126 Value::Table(table) => { target = table.get(p); },
127 Value::Array(array) => {
128 if let Ok(index) = p.parse::<usize>() {
129 target = array.get(index);
130 }
131 },
132 _ => { return None; }
133 }
134 }
135 return target;
136 }
137
138 fn apply_mut<'tr>(&self, v: &'tr mut Value) -> Option<&'tr mut Value> {
141 let mut target = Some(v);
142 for p in &self.paths {
143 if target.is_none() {
144 return None;
145 }
146 if p.is_empty() {
147 continue;
148 }
149 match p.parse::<usize>() {
150 Ok(index) => { target = target.unwrap().get_mut(index); },
151 Err(_) => { target = target.unwrap().get_mut(p); },
152 }
153 }
154 return target;
155 }
156}
157
158trait PathBuilder {
160 fn build_path(&self) -> PathSegment {
161 PathSegment { paths: Vec::new() }
162 }
163}
164
165impl PathBuilder for &str {
167 fn build_path(&self) -> PathSegment {
168 let paths = self
169 .split(|c| c == '/' || c == '.')
170 .map(|s| s.to_string())
171 .collect();
172 PathSegment { paths }
173 }
174}
175
176impl PathBuilder for usize {}
178
179pub trait PathOperator
181{
182 fn path<'tr>(&'tr self) -> TomlPtr<'tr>;
184
185 fn pathto<'tr>(&'tr self, p: &str) -> TomlPtr<'tr>;
187
188 fn path_mut<'tr>(&'tr mut self) -> TomlPtrMut<'tr>;
190
191 fn pathto_mut<'tr>(&'tr mut self, p: &str) -> TomlPtrMut<'tr>;
193}
194
195impl PathOperator for Value
197{
198 fn path<'tr>(&'tr self) -> TomlPtr<'tr> {
199 TomlPtr::path(self)
200 }
201 fn pathto<'tr>(&'tr self, p: &str) -> TomlPtr<'tr> {
202 let valop = p.build_path().apply(self);
203 TomlPtr { valop }
204 }
205
206 fn path_mut<'tr>(&'tr mut self) -> TomlPtrMut<'tr> {
207 TomlPtrMut::path(self)
208 }
209 fn pathto_mut<'tr>(&'tr mut self, p: &str) -> TomlPtrMut<'tr> {
210 let valop = p.build_path().apply_mut(self);
211 TomlPtrMut { valop }
212 }
213}
214
215#[derive(Copy, Clone)]
218pub struct TomlPtr<'tr> {
219 valop: Option<&'tr Value>,
220}
221
222impl<'tr> TomlPtr<'tr> {
223 pub fn path(v: &'tr Value) -> Self {
225 Self { valop: Some(v) }
226 }
227
228 pub fn unpath(&self) -> &Option<&'tr Value> {
230 &self.valop
231 }
232}
233
234impl<'tr> Not for TomlPtr<'tr> {
236 type Output = bool;
237 fn not(self) -> Self::Output {
238 self.valop.is_none()
239 }
240}
241
242impl<'tr> Deref for TomlPtr<'tr>
244{
245 type Target = Option<&'tr Value>;
246 fn deref(&self) -> &Self::Target {
247 self.unpath()
248 }
249}
250
251impl<'tr, Rhs> Div<Rhs> for TomlPtr<'tr>
254where Rhs: PathBuilder + Index + Copy
255{
256 type Output = Self;
257 fn div(self, rhs: Rhs) -> Self::Output {
258 TomlPtr { valop: path(self.valop, rhs) }
259 }
260}
261
262impl<'tr> BitOr<String> for TomlPtr<'tr>
274{
275 type Output = String;
276 fn bitor(self, rhs: String) -> Self::Output {
277 if self.valop.is_none() {
278 return rhs;
279 }
280 match self.valop.unwrap().as_str() {
281 Some(s) => s.to_string(),
282 None => rhs
283 }
284 }
285}
286
287impl<'tr> BitOr<&'static str> for TomlPtr<'tr>
289{
290 type Output = &'tr str;
291 fn bitor(self, rhs: &'static str) -> Self::Output {
292 match self.valop {
293 Some(v) => v.as_str().unwrap_or(rhs),
294 None => rhs,
295 }
296 }
297}
298
299impl<'tr> BitOr<i64> for TomlPtr<'tr>
301{
302 type Output = i64;
303 fn bitor(self, rhs: i64) -> Self::Output {
304 match self.valop {
305 Some(v) => v.as_integer().unwrap_or(rhs),
306 None => rhs,
307 }
308 }
309}
310
311impl<'tr> BitOr<f64> for TomlPtr<'tr>
313{
314 type Output = f64;
315 fn bitor(self, rhs: f64) -> Self::Output {
316 match self.valop {
317 Some(v) => v.as_float().unwrap_or(rhs),
318 None => rhs,
319 }
320 }
321}
322
323impl<'tr> BitOr<bool> for TomlPtr<'tr>
325{
326 type Output = bool;
327 fn bitor(self, rhs: bool) -> Self::Output {
328 match self.valop {
329 Some(v) => v.as_bool().unwrap_or(rhs),
330 None => rhs,
331 }
332 }
333}
334
335pub struct TomlPtrMut<'tr> {
339 valop: Option<&'tr mut Value>,
340}
341
342impl<'tr> TomlPtrMut<'tr> {
343 pub fn path(v: &'tr mut Value) -> Self {
345 Self { valop: Some(v) }
346 }
347
348 pub fn unpath(&self) -> &Option<&'tr mut Value> {
350 &self.valop
351 }
352
353 pub fn assign<T>(&mut self, rhs: T) where Value: From<T> {
356 if let Some(ref mut v) = self.valop {
357 **v = Value::from(rhs);
358 }
359 }
360
361 fn none() -> Self {
363 Self { valop: None }
364 }
365
366 fn put_val<T>(v: &'tr mut Value, rhs: T) -> Self
368 where Value: From<T>
369 {
370 *v = Value::from(rhs);
371 Self::path(v)
372 }
373
374 fn put_string(&mut self, rhs: String) -> Self {
377 if self.valop.is_none() {
378 return Self::none();
379 }
380 let v = self.valop.take().unwrap();
381 if v.is_str() {
382 return Self::put_val(v, rhs);
383 }
384 return Self::none();
385 }
386
387 fn put_integer(&mut self, rhs: i64) -> Self {
389 if self.valop.is_none() {
390 return Self::none();
391 }
392 let v = self.valop.take().unwrap();
393 if v.is_integer() {
394 return Self::put_val(v, rhs);
395 }
396 return Self::none();
397 }
398
399 fn put_float(&mut self, rhs: f64) -> Self {
401 if self.valop.is_none() {
402 return Self::none();
403 }
404 let v = self.valop.take().unwrap();
405 if v.is_float() {
406 return Self::put_val(v, rhs);
407 }
408 return Self::none();
409 }
410
411 fn put_bool(&mut self, rhs: bool) -> Self {
413 if self.valop.is_none() {
414 return Self::none();
415 }
416 let v = self.valop.take().unwrap();
417 if v.is_bool() {
418 return Self::put_val(v, rhs);
419 }
420 return Self::none();
421 }
422
423 fn push_table<K: ToString, T>(&mut self, key: K, val: T) -> Self
425 where Value: From<T>
426 {
427 if self.valop.is_none() {
428 return Self::none();
429 }
430 let v = self.valop.take().unwrap();
431 if v.is_table() {
432 v.as_table_mut().unwrap().insert(key.to_string(), Value::from(val));
433 return Self::path(v);
434 }
435 return Self::none();
436 }
437
438 fn push_array<T>(&mut self, val: T) -> Self
440 where Value: From<T>
441 {
442 if self.valop.is_none() {
443 return Self::none();
444 }
445 let v = self.valop.take().unwrap();
446 if v.is_array() {
447 v.as_array_mut().unwrap().push(Value::from(val));
448 return Self::path(v);
449 }
450 return Self::none();
451 }
452}
453
454impl<'tr> Not for TomlPtrMut<'tr> {
456 type Output = bool;
457 fn not(self) -> Self::Output {
458 self.valop.is_none()
459 }
460}
461
462impl<'tr> Deref for TomlPtrMut<'tr> {
464 type Target = Option<&'tr mut Value>;
465 fn deref(&self) -> &Self::Target {
466 &self.valop
467 }
468}
469
470impl<'tr> DerefMut for TomlPtrMut<'tr> {
472 fn deref_mut(&mut self) -> &mut Self::Target {
473 &mut self.valop
474 }
475}
476
477impl<'tr, Rhs> Div<Rhs> for TomlPtrMut<'tr>
481where Rhs: PathBuilder + Index + Copy
482{
483 type Output = Self;
484
485 fn div(self, rhs: Rhs) -> Self::Output {
486 TomlPtrMut { valop: path_mut(self.valop, rhs) }
487 }
488}
489
490impl<'tr> BitOr<String> for TomlPtrMut<'tr>
494{
495 type Output = String;
496 fn bitor(self, rhs: String) -> Self::Output {
497 if self.valop.is_none() {
498 return rhs;
499 }
500 match self.valop.unwrap().as_str() {
501 Some(s) => s.to_string(),
502 None => rhs
503 }
504 }
505}
506
507impl<'tr> BitOr<&'static str> for TomlPtrMut<'tr>
509{
510 type Output = &'tr str;
511 fn bitor(self, rhs: &'static str) -> Self::Output {
512 match self.valop {
513 Some(v) => v.as_str().unwrap_or(rhs),
514 None => rhs,
515 }
516 }
517}
518
519impl<'tr> BitOr<i64> for TomlPtrMut<'tr>
521{
522 type Output = i64;
523 fn bitor(self, rhs: i64) -> Self::Output {
524 match self.valop {
525 Some(v) => v.as_integer().unwrap_or(rhs),
526 None => rhs,
527 }
528 }
529}
530
531impl<'tr> BitOr<f64> for TomlPtrMut<'tr>
533{
534 type Output = f64;
535 fn bitor(self, rhs: f64) -> Self::Output {
536 match self.valop {
537 Some(v) => v.as_float().unwrap_or(rhs),
538 None => rhs,
539 }
540 }
541}
542
543impl<'tr> BitOr<bool> for TomlPtrMut<'tr>
545{
546 type Output = bool;
547 fn bitor(self, rhs: bool) -> Self::Output {
548 match self.valop {
549 Some(v) => v.as_bool().unwrap_or(rhs),
550 None => rhs,
551 }
552 }
553}
554
555impl<'tr> Shl<&str> for TomlPtrMut<'tr> {
558 type Output = Self;
559 fn shl(mut self, rhs: &str) -> Self::Output {
560 self.put_string(rhs.to_string())
561 }
562}
563
564impl<'tr> Shl<String> for TomlPtrMut<'tr> {
567 type Output = Self;
568 fn shl(mut self, rhs: String) -> Self::Output {
569 self.put_string(rhs)
570 }
571}
572
573impl<'tr> Shl<i64> for TomlPtrMut<'tr> {
576 type Output = Self;
577 fn shl(mut self, rhs: i64) -> Self::Output {
578 self.put_integer(rhs)
579 }
580}
581
582impl<'tr> Shl<f64> for TomlPtrMut<'tr> {
585 type Output = Self;
586 fn shl(mut self, rhs: f64) -> Self::Output {
587 self.put_float(rhs)
588 }
589}
590
591impl<'tr> Shl<bool> for TomlPtrMut<'tr> {
594 type Output = Self;
595 fn shl(mut self, rhs: bool) -> Self::Output {
596 self.put_bool(rhs)
597 }
598}
599
600impl<'tr, K: ToString, T> Shl<(K, T)> for TomlPtrMut<'tr> where Value: From<T>
603{
604 type Output = Self;
605 fn shl(mut self, rhs: (K, T)) -> Self::Output {
606 self.push_table(rhs.0, rhs.1)
607 }
608}
609
610impl<'tr, T> Shl<(T,)> for TomlPtrMut<'tr> where Value: From<T>
614{
615 type Output = Self;
616 fn shl(mut self, rhs: (T,)) -> Self::Output {
617 self.push_array(rhs.0)
618 }
619}
620
621impl<'tr, T: Copy> Shl<[T;1]> for TomlPtrMut<'tr> where Value: From<T>
624{
625 type Output = Self;
626 fn shl(mut self, rhs: [T;1]) -> Self::Output {
627 self.push_array(rhs[0])
628 }
629}
630
631impl<'tr, T: Copy> Shl<&[T]> for TomlPtrMut<'tr> where Value: From<T>
634{
635 type Output = Self;
636 fn shl(mut self, rhs: &[T]) -> Self::Output {
637 for item in rhs {
638 self = self.push_array(*item);
639 }
640 self
641 }
642}
643
644impl<'tr, T> ShlAssign<T> for TomlPtrMut<'tr> where Value: From<T>
647{
648 fn shl_assign(&mut self, rhs: T) {
649 self.assign(rhs);
650 }
651}
652
653#[cfg(test)]
654mod tests;