1use crate::{Error, dofigen_struct::*};
2#[cfg(feature = "json_schema")]
3use schemars::JsonSchema;
4use serde::{Deserialize, Deserializer, de};
5use std::{
6 cmp::Ordering,
7 collections::{BTreeMap, HashMap},
8 fmt,
9 hash::Hash,
10 marker::PhantomData,
11 usize,
12};
13#[cfg(feature = "permissive")]
14use std::{ops::Deref, str::FromStr};
15use struct_patch::{Merge, Patch};
16
17macro_rules! impl_from_patch_and_add {
19 ($struct:ty, $patch:ty) => {
20 impl From<$patch> for $struct {
21 fn from(value: $patch) -> Self {
22 let mut s = Self::default();
23 s.apply(value);
24 s
25 }
26 }
27 };
28}
29
30impl_from_patch_and_add!(Dofigen, DofigenPatch);
31impl_from_patch_and_add!(Stage, StagePatch);
32impl_from_patch_and_add!(Healthcheck, HealthcheckPatch);
33impl_from_patch_and_add!(ImageName, ImageNamePatch);
34impl_from_patch_and_add!(Run, RunPatch);
35impl_from_patch_and_add!(Cache, CachePatch);
36impl_from_patch_and_add!(Bind, BindPatch);
37impl_from_patch_and_add!(Port, PortPatch);
38impl_from_patch_and_add!(User, UserPatch);
39impl_from_patch_and_add!(CopyOptions, CopyOptionsPatch);
40impl_from_patch_and_add!(Copy, CopyPatch);
41impl_from_patch_and_add!(CopyContent, CopyContentPatch);
42impl_from_patch_and_add!(Add, AddPatch);
43impl_from_patch_and_add!(AddGitRepo, AddGitRepoPatch);
44
45#[cfg(feature = "permissive")]
49#[derive(Debug, Clone, PartialEq, Default)]
50pub struct ParsableStruct<T>(pub(crate) T)
51where
52 T: FromStr;
53
54#[cfg(feature = "permissive")]
56#[derive(Deserialize, Debug, Clone, PartialEq)]
57#[serde(from = "OneOrManyDeserializable<T>")]
58pub struct OneOrMany<T>(pub Vec<T>);
59
60#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
67#[serde(from = "VecPatchDeserializable<T>")]
68pub struct VecPatch<T>
69where
70 T: Clone,
71{
72 commands: Vec<VecPatchCommand<T>>,
73}
74
75#[derive(Debug, Clone, PartialEq)]
76enum VecPatchCommand<T> {
77 ReplaceAll(Vec<T>),
78 Replace(usize, T),
79 InsertBefore(usize, Vec<T>),
80 InsertAfter(usize, Vec<T>),
81 Append(Vec<T>),
82}
83
84#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
92#[serde(
93 from = "VecDeepPatchDeserializable<T, P>",
94 bound(deserialize = "T: Clone + From<P>, P: Clone + Deserialize<'de>")
95)]
96pub struct VecDeepPatch<T, P>
97where
98 T: Clone + Patch<P> + From<P>,
99 P: Clone,
100{
101 commands: Vec<VecDeepPatchCommand<T, P>>,
102}
103
104#[derive(Debug, Clone, PartialEq)]
105enum VecDeepPatchCommand<T, P>
106where
107 T: Clone,
108{
109 ReplaceAll(Vec<T>),
110 Replace(usize, T),
111 Patch(usize, P),
112 InsertBefore(usize, Vec<T>),
113 InsertAfter(usize, Vec<T>),
114 Append(Vec<T>),
115}
116
117#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
118pub struct HashMapPatch<K, V>
119where
120 K: Clone + Eq + std::hash::Hash,
121 V: Clone,
122{
123 #[serde(flatten)]
124 patches: HashMap<K, Option<V>>,
125}
126
127#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
128pub struct HashMapDeepPatch<K, V>
129where
130 K: Clone + Eq + std::hash::Hash,
131 V: Clone,
132{
133 #[serde(flatten)]
134 patches: HashMap<K, Option<V>>,
135}
136
137#[cfg(not(feature = "strict"))]
139#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
140#[cfg_attr(feature = "json_schema", derive(JsonSchema))]
141pub(crate) struct NestedMap<T>(HashMap<String, NestedMapValue<T>>);
142
143#[cfg(not(feature = "strict"))]
144#[derive(Deserialize, Debug, Clone, PartialEq)]
145#[cfg_attr(feature = "json_schema", derive(JsonSchema))]
146#[serde(untagged)]
147enum NestedMapValue<T> {
148 Value(T),
149 Map(NestedMap<T>),
150 Null,
151}
152
153#[derive(Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
156#[serde(untagged)]
157enum StringOrNumber {
158 String(String),
159 Number(usize),
160}
161
162#[cfg(feature = "permissive")]
164#[derive(Deserialize, Debug, Clone, PartialEq)]
165#[serde(untagged)]
166#[cfg_attr(feature = "json_schema", derive(JsonSchema))]
167enum OneOrManyDeserializable<T> {
168 One(T),
169 Many(Vec<T>),
170}
171
172#[derive(Deserialize, Debug, Clone, PartialEq)]
173#[serde(untagged)]
174enum VecPatchDeserializable<T>
175where
176 T: Clone,
177{
178 #[cfg(feature = "permissive")]
179 Vec(OneOrMany<T>),
180 #[cfg(not(feature = "permissive"))]
181 Vec(Vec<T>),
182 Map(VecPatchCommandMap<T>),
183}
184
185#[derive(Debug, Clone, PartialEq)]
186struct VecPatchCommandMap<T>
187where
188 T: Clone,
189{
190 commands: Vec<VecPatchCommand<T>>,
191}
192
193#[derive(Deserialize, Debug, Clone, PartialEq)]
194#[serde(
195 untagged,
196 bound(deserialize = "T: Clone + From<P> + Patch<P>, P: Clone + Deserialize<'de>")
197)]
198enum VecDeepPatchDeserializable<T, P>
199where
200 T: Clone + From<P>,
201 P: Clone,
202{
203 Map(VecDeepPatchCommandMap<T, P>),
204 #[cfg(feature = "permissive")]
205 Vec(OneOrMany<P>),
206 #[cfg(not(feature = "permissive"))]
207 Vec(Vec<P>),
208}
209
210#[derive(Debug, Clone, PartialEq)]
211struct VecDeepPatchCommandMap<T, P>
212where
213 T: Clone,
214{
215 commands: Vec<VecDeepPatchCommand<T, P>>,
216}
217
218impl From<FromContextPatch> for FromContext {
221 fn from(patch: FromContextPatch) -> Self {
222 match patch {
223 FromContextPatch::FromImage(p) => FromContext::FromImage(p.into()),
224 FromContextPatch::FromBuilder(p) => FromContext::FromBuilder(p),
225 FromContextPatch::FromContext(p) => FromContext::FromContext(p),
226 }
227 }
228}
229
230impl From<ImageName> for FromContext {
231 fn from(image: ImageName) -> Self {
232 FromContext::FromImage(image)
233 }
234}
235
236impl Default for FromContext {
237 fn default() -> Self {
238 FromContext::FromContext(None)
239 }
240}
241
242impl FromContext {
243 pub fn is_empty(&self) -> bool {
244 match self {
245 FromContext::FromContext(p) => p.is_none(),
246 _ => false,
247 }
248 }
249}
250
251impl Default for FromContextPatch {
252 fn default() -> Self {
253 FromContextPatch::FromContext(None)
254 }
255}
256
257impl Default for CopyResourcePatch {
258 fn default() -> Self {
259 CopyResourcePatch::Unknown(UnknownPatch::default())
260 }
261}
262
263impl Default for CacheSharing {
264 fn default() -> Self {
265 CacheSharing::Locked
266 }
267}
268
269impl From<CopyResourcePatch> for CopyResource {
270 fn from(patch: CopyResourcePatch) -> Self {
271 match patch {
272 CopyResourcePatch::Copy(p) => CopyResource::Copy(p.into()),
273 CopyResourcePatch::Content(p) => CopyResource::Content(p.into()),
274 CopyResourcePatch::Add(p) => CopyResource::Add(p.into()),
275 CopyResourcePatch::AddGitRepo(p) => CopyResource::AddGitRepo(p.into()),
276 CopyResourcePatch::Unknown(p) => panic!("Unknown patch: {:?}", p),
277 }
278 }
279}
280
281#[cfg(feature = "permissive")]
282impl<T: FromStr> From<T> for ParsableStruct<T> {
283 fn from(value: T) -> Self {
284 ParsableStruct(value)
285 }
286}
287
288#[cfg(feature = "permissive")]
289impl<T> Default for OneOrMany<T>
290where
291 T: Sized,
292{
293 fn default() -> Self {
294 OneOrMany(vec![])
295 }
296}
297
298#[cfg(feature = "permissive")]
299impl<T> Deref for OneOrMany<T>
300where
301 T: Sized,
302{
303 type Target = Vec<T>;
304
305 fn deref(&self) -> &Self::Target {
306 &self.0
307 }
308}
309
310#[cfg(feature = "permissive")]
311impl<T> From<OneOrManyDeserializable<T>> for OneOrMany<T> {
312 fn from(value: OneOrManyDeserializable<T>) -> Self {
313 match value {
314 OneOrManyDeserializable::One(v) => OneOrMany(vec![v]),
315 OneOrManyDeserializable::Many(v) => OneOrMany(v),
316 }
317 }
318}
319
320impl<T> From<VecPatchDeserializable<T>> for VecPatch<T>
321where
322 T: Clone,
323{
324 fn from(value: VecPatchDeserializable<T>) -> Self {
325 match value {
326 #[cfg(feature = "permissive")]
327 VecPatchDeserializable::Vec(v) => VecPatch {
328 commands: vec![VecPatchCommand::ReplaceAll(v.0)],
329 },
330 #[cfg(not(feature = "permissive"))]
331 VecPatchDeserializable::Vec(v) => VecPatch {
332 commands: vec![VecPatchCommand::ReplaceAll(v)],
333 },
334 VecPatchDeserializable::Map(v) => VecPatch {
335 commands: v.commands,
336 },
337 }
338 }
339}
340
341impl<T, P> TryFrom<VecDeepPatchCommand<T, P>> for VecPatchCommand<T>
342where
343 T: Clone + From<P>,
344{
345 type Error = Error;
346
347 fn try_from(value: VecDeepPatchCommand<T, P>) -> Result<Self, Error> {
348 Ok(match value {
349 VecDeepPatchCommand::ReplaceAll(v) => VecPatchCommand::ReplaceAll(v),
350 VecDeepPatchCommand::Replace(pos, v) => VecPatchCommand::Replace(pos, v),
351 VecDeepPatchCommand::Patch(pos, _) => {
352 return Err(Error::Custom(format!(
353 "VecPatch don't allow patching on {pos}: '{pos}<'"
354 )));
355 }
356 VecDeepPatchCommand::InsertBefore(pos, v) => VecPatchCommand::InsertBefore(pos, v),
357 VecDeepPatchCommand::InsertAfter(pos, v) => VecPatchCommand::InsertAfter(pos, v),
358 VecDeepPatchCommand::Append(v) => VecPatchCommand::Append(v),
359 })
360 }
361}
362
363impl<T, P> From<VecDeepPatchDeserializable<T, P>> for VecDeepPatch<T, P>
364where
365 T: Clone + Patch<P> + From<P>,
366 P: Clone,
367{
368 fn from(value: VecDeepPatchDeserializable<T, P>) -> Self {
369 match value {
370 #[cfg(feature = "permissive")]
371 VecDeepPatchDeserializable::Vec(v) => VecDeepPatch {
372 commands: vec![VecDeepPatchCommand::ReplaceAll(
373 v.0.iter().map(|p| p.clone().into()).collect(),
374 )],
375 },
376 #[cfg(not(feature = "permissive"))]
377 VecDeepPatchDeserializable::Vec(v) => VecDeepPatch {
378 commands: vec![VecDeepPatchCommand::ReplaceAll(
379 v.iter().map(|p| p.clone().into()).collect(),
380 )],
381 },
382 VecDeepPatchDeserializable::Map(v) => VecDeepPatch {
383 commands: v.commands,
384 },
385 }
386 }
387}
388
389#[cfg(not(feature = "strict"))]
390impl<T: Clone> NestedMap<T> {
391 fn flatten(&mut self) {
392 let keys = self.0.keys().cloned().collect::<Vec<_>>();
393 for key in keys {
394 if let Some(NestedMapValue::Map(nested_map)) = self.0.get_mut(&key) {
395 let mut nested_map = nested_map.clone();
396 self.0.remove(&key);
397 nested_map.flatten();
398 for (nested_key, nested_value) in nested_map.0 {
399 let final_key = format!("{key}.{nested_key}");
400 if !self.0.contains_key(&final_key) {
402 self.0.insert(final_key, nested_value);
403 }
404 }
405 }
406 }
407 }
408}
409
410impl Patch<FromContextPatch> for FromContext {
413 fn apply(&mut self, patch: FromContextPatch) {
414 match (self, patch) {
415 (Self::FromImage(s), FromContextPatch::FromImage(p)) => s.apply(p),
416 (s, patch) => *s = patch.into(),
417 }
418 }
419
420 fn into_patch(self) -> FromContextPatch {
421 match self {
422 FromContext::FromImage(s) => FromContextPatch::FromImage(s.into_patch()),
423 FromContext::FromBuilder(s) => FromContextPatch::FromBuilder(s),
424 FromContext::FromContext(s) => FromContextPatch::FromContext(s),
425 }
426 }
427
428 fn into_patch_by_diff(self, _previous_struct: Self) -> FromContextPatch {
429 todo!()
430 }
431
432 fn new_empty_patch() -> FromContextPatch {
433 panic!("Cannot create an empty patch for FromContext");
434 }
435}
436
437impl Patch<CopyResourcePatch> for CopyResource {
438 fn apply(&mut self, patch: CopyResourcePatch) {
439 match (self, patch) {
440 (Self::Copy(s), CopyResourcePatch::Copy(p)) => s.apply(p),
441 (Self::Copy(s), CopyResourcePatch::Unknown(p)) => s.apply(p),
442 (Self::Content(s), CopyResourcePatch::Content(p)) => s.apply(p),
443 (Self::Content(s), CopyResourcePatch::Unknown(p)) => s.apply(p),
444 (Self::Add(s), CopyResourcePatch::Add(p)) => s.apply(p),
445 (Self::Add(s), CopyResourcePatch::Unknown(p)) => s.apply(p),
446 (Self::AddGitRepo(s), CopyResourcePatch::AddGitRepo(p)) => s.apply(p),
447 (Self::AddGitRepo(s), CopyResourcePatch::Unknown(p)) => s.apply(p),
448 (s, p) => panic!("Cannot apply patch {:?} on {:?}", p, s),
449 }
450 }
451
452 fn into_patch(self) -> CopyResourcePatch {
453 match self {
454 CopyResource::Copy(s) => CopyResourcePatch::Copy(s.into_patch()),
455 CopyResource::Content(s) => CopyResourcePatch::Content(s.into_patch()),
456 CopyResource::Add(s) => CopyResourcePatch::Add(s.into_patch()),
457 CopyResource::AddGitRepo(s) => CopyResourcePatch::AddGitRepo(s.into_patch()),
458 }
459 }
460
461 fn into_patch_by_diff(self, previous_struct: Self) -> CopyResourcePatch {
462 match (self, previous_struct) {
463 (CopyResource::Copy(s), CopyResource::Copy(p)) => {
464 CopyResourcePatch::Copy(s.into_patch_by_diff(p))
465 }
466 (CopyResource::Add(s), CopyResource::Add(p)) => {
467 CopyResourcePatch::Add(s.into_patch_by_diff(p))
468 }
469 (CopyResource::AddGitRepo(s), CopyResource::AddGitRepo(p)) => {
470 CopyResourcePatch::AddGitRepo(s.into_patch_by_diff(p))
471 }
472 _ => todo!(),
473 }
474 }
475
476 fn new_empty_patch() -> CopyResourcePatch {
477 CopyResourcePatch::default()
478 }
479}
480
481impl Patch<UnknownPatch> for Copy {
482 fn apply(&mut self, patch: UnknownPatch) {
483 if let Some(options) = patch.options {
484 self.options.apply(options);
485 }
486 }
487
488 fn into_patch(self) -> UnknownPatch {
489 UnknownPatch {
490 options: Some(self.options.into_patch()),
491 exclude: Some(self.exclude.into_patch()),
492 }
493 }
494
495 fn into_patch_by_diff(self, previous_struct: Self) -> UnknownPatch {
496 UnknownPatch {
497 options: Some(self.options.into_patch_by_diff(previous_struct.options)),
498 exclude: Some(self.exclude.into_patch_by_diff(previous_struct.exclude)),
499 }
500 }
501
502 fn new_empty_patch() -> UnknownPatch {
503 UnknownPatch::default()
504 }
505}
506
507impl Patch<UnknownPatch> for CopyContent {
508 fn apply(&mut self, patch: UnknownPatch) {
509 if let Some(options) = patch.options {
510 self.options.apply(options);
511 }
512 }
513
514 fn into_patch(self) -> UnknownPatch {
515 UnknownPatch {
516 options: Some(self.options.into_patch()),
517 exclude: None,
518 }
519 }
520
521 fn into_patch_by_diff(self, previous_struct: Self) -> UnknownPatch {
522 UnknownPatch {
523 options: Some(self.options.into_patch_by_diff(previous_struct.options)),
524 exclude: None,
525 }
526 }
527
528 fn new_empty_patch() -> UnknownPatch {
529 UnknownPatch::default()
530 }
531}
532
533impl Patch<UnknownPatch> for Add {
534 fn apply(&mut self, patch: UnknownPatch) {
535 if let Some(options) = patch.options {
536 self.options.apply(options);
537 }
538 }
539
540 fn into_patch(self) -> UnknownPatch {
541 UnknownPatch {
542 options: Some(self.options.into_patch()),
543 exclude: None,
544 }
545 }
546
547 fn into_patch_by_diff(self, previous_struct: Self) -> UnknownPatch {
548 UnknownPatch {
549 options: Some(self.options.into_patch_by_diff(previous_struct.options)),
550 exclude: None,
551 }
552 }
553
554 fn new_empty_patch() -> UnknownPatch {
555 UnknownPatch::default()
556 }
557}
558
559impl Patch<UnknownPatch> for AddGitRepo {
560 fn apply(&mut self, patch: UnknownPatch) {
561 if let Some(options) = patch.options {
562 self.options.apply(options);
563 }
564 }
565
566 fn into_patch(self) -> UnknownPatch {
567 UnknownPatch {
568 options: Some(self.options.into_patch()),
569 exclude: Some(self.exclude.into_patch()),
570 }
571 }
572
573 fn into_patch_by_diff(self, previous_struct: Self) -> UnknownPatch {
574 UnknownPatch {
575 options: Some(self.options.into_patch_by_diff(previous_struct.options)),
576 exclude: Some(self.exclude.into_patch_by_diff(previous_struct.exclude)),
577 }
578 }
579
580 fn new_empty_patch() -> UnknownPatch {
581 UnknownPatch::default()
582 }
583}
584
585impl<T> Patch<VecPatch<T>> for Vec<T>
586where
587 T: Clone,
588{
589 fn apply(&mut self, patch: VecPatch<T>) {
590 let mut reset = false;
591 let mut last_modified_position: usize = usize::MAX;
592 let initial_len = self.len();
594 let mut adapted_positions: Vec<usize> = vec![0; self.len()];
596 let mut current_position = 0;
598 let mut position_adaptation = 0;
599
600 for command in patch.commands {
601 match command {
602 VecPatchCommand::ReplaceAll(elements) => {
603 if reset {
604 panic!("Cannot replace the list twice");
605 }
606 reset = true;
607 self.clear();
608 self.extend(elements.into_iter());
609 }
610 VecPatchCommand::Replace(pos, elements) => {
611 if reset {
612 panic!("Cannot replace element at position {} after a reset", pos);
613 }
614 if pos >= initial_len {
615 panic!("Position {} is out of bounds", pos);
616 }
617 if pos == last_modified_position {
618 panic!(
619 "Cannot replace element at position {} after another modification on it",
620 pos
621 );
622 }
623 for i in current_position..=pos {
624 current_position = i;
625 position_adaptation += adapted_positions[i];
626 }
627 let adapted_position = current_position + position_adaptation;
628 self[adapted_position] = elements;
629 last_modified_position = pos;
630 }
631 VecPatchCommand::InsertBefore(pos, elements) => {
632 if reset {
633 panic!(
634 "Cannot insert before element at position {} after a reset",
635 pos
636 );
637 }
638 if pos >= initial_len {
639 panic!("Position {} is out of bounds", pos);
640 }
641 for i in current_position..=pos {
642 current_position = i;
643 position_adaptation += adapted_positions[i];
644 }
645 let added = elements.len();
646 let adapted_position = current_position + position_adaptation;
647 self.splice(adapted_position..adapted_position, elements);
648 adapted_positions[pos as usize] += added;
649 }
650 VecPatchCommand::InsertAfter(pos, elements) => {
651 if reset {
652 panic!(
653 "Cannot insert after element at position {} after a reset",
654 pos
655 );
656 }
657 if pos >= initial_len {
658 panic!("Position {} is out of bounds", pos);
659 }
660 for i in current_position..=pos {
661 current_position = i;
662 position_adaptation += adapted_positions[i];
663 }
664 let adapted_position = current_position + position_adaptation + 1;
665 let added = elements.len();
666 self.splice(adapted_position..adapted_position, elements);
667 if pos + 1 < initial_len {
668 adapted_positions[(pos + 1) as usize] = added;
669 } else {
670 adapted_positions.push(added);
671 }
672 }
673 VecPatchCommand::Append(elements) => {
674 self.extend(elements);
675 }
676 }
677 }
678 }
679
680 fn into_patch(self) -> VecPatch<T> {
681 VecPatch {
682 commands: vec![VecPatchCommand::ReplaceAll(self)],
683 }
684 }
685
686 fn into_patch_by_diff(self, _previous_struct: Self) -> VecPatch<T> {
687 todo!()
688 }
693
694 fn new_empty_patch() -> VecPatch<T> {
695 VecPatch { commands: vec![] }
696 }
697}
698
699impl<T, P> Patch<VecDeepPatch<T, P>> for Vec<T>
700where
701 T: Clone + Patch<P> + From<P>,
702 P: Clone,
703{
704 fn apply(&mut self, patch: VecDeepPatch<T, P>) {
705 let mut reset = false;
706 let mut last_modified_position: usize = usize::MAX;
707 let initial_len = self.len();
709 let patch_len = patch.commands.len();
710 let mut adapted_positions: Vec<usize> = vec![0; self.len()];
712 let mut current_position = 0;
714 let mut position_adaptation = 0;
715
716 for command in patch.commands {
717 match command {
718 VecDeepPatchCommand::ReplaceAll(elements) => {
719 if reset {
720 panic!("Cannot replace the list twice");
721 }
722 if patch_len > 1 {
723 panic!("Cannot combine a replace all with other commands");
724 }
725 reset = true;
726 self.clear();
727 self.extend(elements.into_iter());
728 }
729 VecDeepPatchCommand::Replace(pos, element) => {
730 if reset {
731 panic!("Cannot replace element at position {} after a reset", pos);
732 }
733 if pos >= initial_len {
734 panic!("Position {} is out of bounds", pos);
735 }
736 if pos == last_modified_position {
737 panic!(
738 "Cannot replace element at position {} after another modification on it",
739 pos
740 );
741 }
742 for i in current_position..=pos {
743 current_position = i;
744 position_adaptation += adapted_positions[i];
745 }
746 let adapted_position = current_position + position_adaptation;
747 self[adapted_position] = element;
748 last_modified_position = pos;
749 }
750 VecDeepPatchCommand::Patch(pos, element) => {
751 if reset {
752 panic!("Cannot patch element at position {} after a reset", pos);
753 }
754 if pos >= initial_len {
755 panic!("Position {} is out of bounds", pos);
756 }
757 if pos == last_modified_position {
758 panic!(
759 "Cannot patch element at position {} after another modification on it",
760 pos
761 );
762 }
763 for i in current_position..=pos {
764 current_position = i;
765 position_adaptation += adapted_positions[i];
766 }
767 let adapted_position = current_position + position_adaptation;
768 self[adapted_position].apply(element);
769 last_modified_position = pos;
770 }
771 VecDeepPatchCommand::InsertBefore(pos, elements) => {
772 if reset {
773 panic!(
774 "Cannot insert before element at position {} after a reset",
775 pos
776 );
777 }
778 if pos >= initial_len {
779 panic!("Position {} is out of bounds", pos);
780 }
781 for i in current_position..=pos {
782 current_position = i;
783 position_adaptation += adapted_positions[i];
784 }
785 let adapted_position = current_position + position_adaptation;
786 let added = elements.len();
787 self.splice(adapted_position..adapted_position, elements);
788 adapted_positions[pos as usize] += added;
789 }
790 VecDeepPatchCommand::InsertAfter(pos, elements) => {
791 if reset {
792 panic!(
793 "Cannot insert after element at position {} after a reset",
794 pos
795 );
796 }
797 if pos >= initial_len {
798 panic!("Position {} is out of bounds", pos);
799 }
800 for i in current_position..=pos {
801 current_position = i;
802 position_adaptation += adapted_positions[i];
803 }
804 let adapted_position = current_position + position_adaptation;
805 let usize_pos = adapted_position + 1;
806 let added = elements.len();
807 self.splice(usize_pos..usize_pos, elements);
808 if pos + 1 < initial_len {
809 adapted_positions[(pos + 1) as usize] = added;
810 } else {
811 adapted_positions.push(added);
812 }
813 }
814 VecDeepPatchCommand::Append(elements) => {
815 self.extend(elements);
816 }
817 }
818 }
819 }
820
821 fn into_patch(self) -> VecDeepPatch<T, P> {
822 VecDeepPatch {
823 commands: vec![VecDeepPatchCommand::ReplaceAll(self)],
824 }
825 }
826
827 fn into_patch_by_diff(self, _previous_struct: Self) -> VecDeepPatch<T, P> {
828 todo!()
829 }
830
831 fn new_empty_patch() -> VecDeepPatch<T, P> {
832 VecDeepPatch { commands: vec![] }
833 }
834}
835
836impl<K, V> Patch<HashMapPatch<K, V>> for HashMap<K, V>
837where
838 K: Clone + Eq + Hash,
839 V: Clone,
840{
841 fn apply(&mut self, patch: HashMapPatch<K, V>) {
842 for (key, value) in patch.patches {
843 match value {
844 Some(value) => {
845 self.insert(key, value);
846 }
847 None => {
848 self.remove(&key);
849 }
850 }
851 }
852 }
853
854 fn into_patch(self) -> HashMapPatch<K, V> {
855 let mut patches = HashMap::new();
856 for (key, value) in self {
857 patches.insert(key, Some(value));
858 }
859 HashMapPatch { patches }
860 }
861
862 fn into_patch_by_diff(self, _previous_struct: Self) -> HashMapPatch<K, V> {
863 todo!()
864 }
865
866 fn new_empty_patch() -> HashMapPatch<K, V> {
867 HashMapPatch {
868 patches: HashMap::new(),
869 }
870 }
871}
872
873impl<K, T, P> Patch<HashMapDeepPatch<K, P>> for HashMap<K, T>
874where
875 K: Clone + Eq + Hash,
876 T: Clone + Patch<P> + From<P>,
877 P: Clone,
878{
879 fn apply(&mut self, patch: HashMapDeepPatch<K, P>) {
880 for (key, value) in patch.patches {
881 match value {
882 Some(value) => {
883 self.insert(key, value.into());
884 }
885 None => {
886 self.remove(&key);
887 }
888 }
889 }
890 }
891
892 fn into_patch(self) -> HashMapDeepPatch<K, P> {
893 let mut patches = HashMap::new();
894 for (key, value) in self {
895 patches.insert(key, Some(value.into_patch()));
896 }
897 HashMapDeepPatch { patches }
898 }
899
900 fn into_patch_by_diff(self, _previous_struct: Self) -> HashMapDeepPatch<K, P> {
901 todo!()
902 }
903
904 fn new_empty_patch() -> HashMapDeepPatch<K, P> {
905 HashMapDeepPatch {
906 patches: HashMap::new(),
907 }
908 }
909}
910
911#[cfg(not(feature = "strict"))]
912impl<T: Clone> From<NestedMap<T>> for HashMap<String, Option<T>> {
913 fn from(value: NestedMap<T>) -> Self {
914 let mut value = value.clone();
915 value.flatten();
916 return value
917 .0
918 .into_iter()
919 .map(|(key, value)| {
920 (
921 key,
922 match value {
923 NestedMapValue::Value(value) => Some(value),
924 NestedMapValue::Map(_) => unreachable!(),
925 NestedMapValue::Null => None,
926 },
927 )
928 })
929 .collect();
930 }
931}
932
933#[cfg(not(feature = "strict"))]
934impl<T> Patch<NestedMap<T>> for HashMap<String, T>
935where
936 T: Clone,
937{
938 fn apply(&mut self, patch: NestedMap<T>) {
939 let flatten: HashMap<String, Option<T>> = patch.into();
940 flatten.into_iter().for_each(|(key, opt)| {
941 if let Some(value) = opt {
942 self.insert(key, value);
943 } else {
944 self.remove(&key);
945 }
946 });
947 }
948
949 fn into_patch(self) -> NestedMap<T> {
950 NestedMap(
951 self.into_iter()
952 .map(|(key, value)| (key.clone(), NestedMapValue::Value(value)))
953 .collect(),
954 )
955 }
956
957 fn into_patch_by_diff(self, _previous_struct: Self) -> NestedMap<T> {
958 todo!()
959 }
960
961 fn new_empty_patch() -> NestedMap<T> {
962 NestedMap(HashMap::new())
963 }
964}
965
966#[cfg(feature = "permissive")]
969impl<'de, T> Deserialize<'de> for ParsableStruct<T>
970where
971 T: FromStr<Err = serde::de::value::Error> + Sized + Deserialize<'de>,
972{
973 fn deserialize<D>(deserializer: D) -> Result<ParsableStruct<T>, D::Error>
974 where
975 D: Deserializer<'de>,
976 {
977 struct PermissiveStructVisitor<T>(Option<T>);
978
979 impl<'de, T> de::Visitor<'de> for PermissiveStructVisitor<T>
980 where
981 T: Deserialize<'de> + FromStr<Err = serde::de::value::Error>,
982 {
983 type Value = T;
984
985 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
986 formatter.write_str("a number, a string or a map")
987 }
988
989 fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
990 where
991 E: de::Error,
992 {
993 self.visit_str(v.to_string().as_str())
994 }
995
996 fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
997 where
998 E: de::Error,
999 {
1000 self.visit_str(v.to_string().as_str())
1001 }
1002
1003 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
1004 where
1005 E: de::Error,
1006 {
1007 self.visit_str(v.to_string().as_str())
1008 }
1009
1010 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
1011 where
1012 E: de::Error,
1013 {
1014 self.visit_str(v.to_string().as_str())
1015 }
1016
1017 fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
1018 where
1019 E: de::Error,
1020 {
1021 self.visit_str(v.to_string().as_str())
1022 }
1023
1024 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
1025 where
1026 E: de::Error,
1027 {
1028 self.visit_str(v.to_string().as_str())
1029 }
1030
1031 fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
1032 where
1033 E: de::Error,
1034 {
1035 self.visit_str(v.to_string().as_str())
1036 }
1037
1038 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
1039 where
1040 E: de::Error,
1041 {
1042 self.visit_str(v.to_string().as_str())
1043 }
1044
1045 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
1046 where
1047 E: de::Error,
1048 {
1049 self.visit_str(v.to_string().as_str())
1050 }
1051
1052 fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
1053 where
1054 E: de::Error,
1055 {
1056 self.visit_str(v.to_string().as_str())
1057 }
1058
1059 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1060 where
1061 E: de::Error,
1062 {
1063 v.parse().map_err(|err| {
1064 E::custom(format!("Error while parsing a permissive struct: {}", err))
1065 })
1066 }
1067
1068 fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
1069 where
1070 A: de::MapAccess<'de>,
1071 {
1072 Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))
1073 }
1074 }
1075
1076 let visitor: PermissiveStructVisitor<T> = PermissiveStructVisitor(None);
1077
1078 deserializer.deserialize_any(visitor).map(ParsableStruct)
1079 }
1080}
1081
1082impl<'de, T> Deserialize<'de> for VecPatchCommandMap<T>
1083where
1084 T: Clone + Deserialize<'de>,
1085{
1086 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1087 where
1088 D: Deserializer<'de>,
1089 {
1090 let commands: Vec<VecDeepPatchCommand<T, T>> =
1091 deserialize_vec_patch_commands(deserializer)?;
1092 Ok(VecPatchCommandMap {
1093 commands: commands
1094 .iter()
1095 .map(|c| c.clone().try_into().map_err(de::Error::custom))
1096 .collect::<Result<Vec<_>, _>>()?,
1097 })
1098 }
1099}
1100
1101impl<'de, T, P> Deserialize<'de> for VecDeepPatchCommandMap<T, P>
1102where
1103 T: Clone + From<P>,
1104 P: Clone + Deserialize<'de>,
1105{
1106 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1107 where
1108 D: Deserializer<'de>,
1109 {
1110 Ok(VecDeepPatchCommandMap {
1111 commands: deserialize_vec_patch_commands(deserializer)?,
1112 })
1113 }
1114}
1115
1116fn deserialize_vec_patch_commands<'de, D, T, P>(
1117 deserializer: D,
1118) -> Result<Vec<VecDeepPatchCommand<T, P>>, D::Error>
1119where
1120 D: Deserializer<'de>,
1121 T: Clone + From<P>,
1122 P: Clone + Deserialize<'de>,
1123{
1124 struct VecDeepPatchCommandsVisitor<T, P>(PhantomData<fn() -> BTreeMap<T, P>>);
1125
1126 #[cfg(feature = "permissive")]
1127 fn map_vec<T, P>(patch: OneOrMany<P>) -> Vec<T>
1128 where
1129 T: Clone + From<P>,
1130 P: Clone,
1131 {
1132 patch.iter().map(|p| p.clone().into()).collect()
1133 }
1134
1135 #[cfg(not(feature = "permissive"))]
1136 fn map_vec<T, P>(patch: Vec<P>) -> Vec<T>
1137 where
1138 T: Clone + From<P>,
1139 P: Clone,
1140 {
1141 patch.iter().map(|p| p.clone().into()).collect()
1142 }
1143
1144 impl<'de, T, P> de::Visitor<'de> for VecDeepPatchCommandsVisitor<T, P>
1145 where
1146 T: Clone + From<P>,
1147 P: Clone + Deserialize<'de>,
1148 {
1149 type Value = Vec<VecDeepPatchCommand<T, P>>;
1150
1151 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1152 formatter.write_str("a map")
1153 }
1154
1155 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1156 where
1157 A: de::MapAccess<'de>,
1158 {
1159 let mut commands = vec![];
1160
1161 while let Some(key) = map.next_key()? {
1162 match key {
1163 StringOrNumber::String(key) => match key.as_str() {
1164 "_" => {
1165 commands
1166 .push(VecDeepPatchCommand::ReplaceAll(map_vec(map.next_value()?)));
1167 }
1168 "+" => {
1169 commands.push(VecDeepPatchCommand::Append(map_vec(map.next_value()?)));
1170 }
1171 key => {
1172 if key.starts_with('+') {
1173 let pos = key[1..key.len()].parse::<usize>().unwrap();
1174 commands.push(VecDeepPatchCommand::InsertBefore(
1175 pos,
1176 map_vec(map.next_value()?),
1177 ));
1178 } else if key.ends_with('+') {
1179 let pos = key[..key.len() - 1].parse::<usize>().unwrap();
1180 commands.push(VecDeepPatchCommand::InsertAfter(
1181 pos,
1182 map_vec(map.next_value()?),
1183 ));
1184 } else if key.ends_with('<') {
1185 let pos = key[..key.len() - 1].parse::<usize>().unwrap();
1186 commands.push(VecDeepPatchCommand::Patch(pos, map.next_value()?));
1187 } else {
1188 let value: P = map.next_value()?;
1189 let pos = key.parse::<usize>().unwrap();
1190 commands.push(VecDeepPatchCommand::Replace(pos, value.into()));
1191 }
1192 }
1193 },
1194 StringOrNumber::Number(pos) => {
1195 let value: P = map.next_value()?;
1196 commands.push(VecDeepPatchCommand::Replace(pos, value.into()));
1197 }
1198 }
1199 }
1200
1201 commands.sort_by(sort_commands);
1203
1204 Ok(commands)
1205 }
1206 }
1207
1208 let visitor: VecDeepPatchCommandsVisitor<T, P> = VecDeepPatchCommandsVisitor(PhantomData);
1209
1210 deserializer.deserialize_any(visitor)
1211}
1212
1213#[cfg(feature = "permissive")]
1214pub(crate) fn deserialize_from_optional_string_or_number<'de, D>(
1215 deserializer: D,
1216) -> Result<Option<Option<String>>, D::Error>
1217where
1218 D: Deserializer<'de>,
1219{
1220 let val: Option<StringOrNumber> = Deserialize::deserialize(deserializer)?;
1221
1222 Ok(Some(val.map(|val| match val {
1223 StringOrNumber::String(s) => s,
1224 StringOrNumber::Number(n) => n.to_string(),
1225 })))
1226}
1227
1228fn sort_commands<T, P>(a: &VecDeepPatchCommand<T, P>, b: &VecDeepPatchCommand<T, P>) -> Ordering
1229where
1230 T: Clone + From<P>,
1231 P: Clone,
1232{
1233 match (a, b) {
1234 (VecDeepPatchCommand::ReplaceAll(_), _) => std::cmp::Ordering::Less,
1236 (_, VecDeepPatchCommand::ReplaceAll(_)) => std::cmp::Ordering::Greater,
1237 (VecDeepPatchCommand::Append(_), _) => std::cmp::Ordering::Greater,
1239 (_, VecDeepPatchCommand::Append(_)) => std::cmp::Ordering::Less,
1240 (VecDeepPatchCommand::InsertBefore(a, _), VecDeepPatchCommand::InsertBefore(b, _))
1242 | (
1243 VecDeepPatchCommand::Replace(a, _) | VecDeepPatchCommand::Patch(a, _),
1244 VecDeepPatchCommand::Replace(b, _) | VecDeepPatchCommand::Patch(b, _),
1245 )
1246 | (VecDeepPatchCommand::InsertAfter(a, _), VecDeepPatchCommand::InsertAfter(b, _)) => {
1247 a.cmp(b)
1248 }
1249 (
1255 VecDeepPatchCommand::InsertBefore(a, _),
1256 VecDeepPatchCommand::Replace(b, _)
1257 | VecDeepPatchCommand::Patch(b, _)
1258 | VecDeepPatchCommand::InsertAfter(b, _),
1259 )
1260 | (
1261 VecDeepPatchCommand::Replace(a, _) | VecDeepPatchCommand::Patch(a, _),
1262 VecDeepPatchCommand::InsertAfter(b, _),
1263 ) => match a.cmp(b) {
1264 std::cmp::Ordering::Equal => std::cmp::Ordering::Less,
1265 other => other,
1266 },
1267 (
1268 VecDeepPatchCommand::Replace(a, _)
1269 | VecDeepPatchCommand::Patch(a, _)
1270 | VecDeepPatchCommand::InsertAfter(a, _),
1271 VecDeepPatchCommand::InsertBefore(b, _),
1272 )
1273 | (
1274 VecDeepPatchCommand::InsertAfter(a, _),
1275 VecDeepPatchCommand::Replace(b, _) | VecDeepPatchCommand::Patch(b, _),
1276 ) => match a.cmp(b) {
1277 std::cmp::Ordering::Equal => std::cmp::Ordering::Greater,
1278 other => other,
1279 },
1280 }
1281}
1282
1283macro_rules! merge_option_patch {
1287 ($opt_a: expr_2021, $opt_b: expr_2021) => {
1288 match ($opt_a, $opt_b) {
1289 (Some(a), Some(b)) => Some(a.merge(b)),
1290 (Some(a), None) => Some(a),
1291 (None, Some(b)) => Some(b),
1292 (None, None) => None,
1293 }
1294 };
1295}
1296
1297impl Merge for FromContextPatch {
1298 fn merge(self, other: Self) -> Self {
1299 match (self, other) {
1300 (Self::FromImage(a), Self::FromImage(b)) => Self::FromImage(a.merge(b)),
1301 (_, b) => b,
1302 }
1303 }
1304}
1305
1306impl Merge for CopyResourcePatch {
1307 fn merge(self, other: Self) -> Self {
1308 match (self, other) {
1309 (Self::Copy(a), Self::Copy(b)) => Self::Copy(a.merge(b)),
1310 (Self::Copy(a), Self::Unknown(b)) => {
1311 let mut a = a;
1312 a.options = merge_option_patch!(a.options, b.options);
1313 Self::Copy(a)
1314 }
1315 (Self::Unknown(a), Self::Copy(b)) => {
1316 let mut b = b;
1317 b.options = merge_option_patch!(a.options, b.options);
1318 Self::Copy(b)
1319 }
1320 (Self::Add(a), Self::Add(b)) => Self::Add(a.merge(b)),
1321 (Self::Add(a), Self::Unknown(b)) => {
1322 let mut a = a;
1323 a.options = merge_option_patch!(a.options, b.options);
1324 Self::Add(a)
1325 }
1326 (Self::Unknown(a), Self::Add(b)) => {
1327 let mut b = b;
1328 b.options = merge_option_patch!(a.options, b.options);
1329 Self::Add(b)
1330 }
1331 (Self::AddGitRepo(a), Self::AddGitRepo(b)) => Self::AddGitRepo(a.merge(b)),
1332 (Self::AddGitRepo(a), Self::Unknown(b)) => {
1333 let mut a = a;
1334 a.options = merge_option_patch!(a.options, b.options);
1335 Self::AddGitRepo(a)
1336 }
1337 (Self::Unknown(a), Self::AddGitRepo(b)) => {
1338 let mut b = b;
1339 b.options = merge_option_patch!(a.options, b.options);
1340 Self::AddGitRepo(b)
1341 }
1342 (Self::Unknown(a), Self::Unknown(b)) => Self::Unknown(a.merge(b)),
1343 (a, b) => panic!("Can't merge {:?} and {:?}", a, b),
1344 }
1345 }
1346}
1347
1348impl Merge for UnknownPatch {
1349 fn merge(self, other: Self) -> Self {
1350 Self {
1351 options: merge_option_patch!(self.options, other.options),
1352 exclude: merge_option_patch!(self.exclude, other.exclude),
1353 }
1354 }
1355}
1356
1357#[cfg(feature = "permissive")]
1358impl<T> Merge for ParsableStruct<T>
1359where
1360 T: Clone + FromStr + Merge,
1361{
1362 fn merge(self, other: Self) -> Self {
1363 ParsableStruct(self.0.merge(other.0))
1364 }
1365}
1366
1367impl<T> Merge for VecPatch<T>
1368where
1369 T: Clone,
1370{
1371 fn merge(self, other: Self) -> Self {
1372 if other.commands.len() == 1
1373 && matches!(other.commands.first(), Some(VecPatchCommand::ReplaceAll(_)))
1374 {
1375 return other;
1376 }
1377 if self.commands.len() == 1 {
1378 if let Some(VecPatchCommand::ReplaceAll(self_vec)) = self.commands.first() {
1379 let mut self_vec = self_vec.clone();
1380 self_vec.apply(other);
1381 return VecPatch {
1382 commands: vec![VecPatchCommand::ReplaceAll(self_vec)],
1383 };
1384 }
1385 }
1386
1387 let mut commands: Vec<VecPatchCommand<T>> = vec![];
1388
1389 let mut self_it = self.commands.iter();
1390 let mut rhs_it = other.commands.iter();
1391
1392 let mut self_next = self_it.next();
1393 let mut rhs_next = rhs_it.next();
1394
1395 while let (Some(self_command), Some(rhs_command)) = (self_next, rhs_next) {
1396 match (self_command.clone(), rhs_command.clone()) {
1397 (VecPatchCommand::ReplaceAll(_), _) | (_, VecPatchCommand::ReplaceAll(_)) => {
1398 panic!("Cannot combine a replace all with other commands");
1399 }
1400 (VecPatchCommand::Append(elements), VecPatchCommand::Append(rhs_elements)) => {
1401 let mut elements = elements;
1404 elements.extend(rhs_elements);
1405 commands.push(VecPatchCommand::Append(elements));
1406 self_next = self_it.next();
1407 rhs_next = rhs_it.next();
1408 }
1409 (self_command, VecPatchCommand::Append(_)) => {
1410 commands.push(self_command);
1411 self_next = self_it.next();
1412 }
1413 (VecPatchCommand::Append(_), rhs_command) => {
1414 commands.push(rhs_command);
1415 rhs_next = rhs_it.next();
1416 }
1417 (
1418 VecPatchCommand::Replace(self_pos, self_val),
1419 VecPatchCommand::Replace(rhs_pos, rhs_val),
1420 ) => {
1421 if self_pos == rhs_pos {
1422 commands.push(VecPatchCommand::Replace(rhs_pos, rhs_val));
1423 self_next = self_it.next();
1424 rhs_next = rhs_it.next();
1425 } else if self_pos < rhs_pos {
1426 commands.push(VecPatchCommand::Replace(self_pos, self_val));
1427 self_next = self_it.next();
1428 } else {
1429 commands.push(VecPatchCommand::Replace(rhs_pos, rhs_val));
1430 rhs_next = rhs_it.next();
1431 }
1432 }
1433 (
1434 VecPatchCommand::InsertBefore(self_pos, self_val),
1435 VecPatchCommand::InsertBefore(rhs_pos, mut rhs_val),
1436 )
1437 | (
1438 VecPatchCommand::InsertAfter(self_pos, self_val),
1439 VecPatchCommand::InsertAfter(rhs_pos, mut rhs_val),
1440 ) => {
1441 if self_pos == rhs_pos {
1442 rhs_val.extend(self_val);
1446 commands.push(rhs_command.clone());
1447 self_next = self_it.next();
1448 rhs_next = rhs_it.next();
1449 } else if self_pos < rhs_pos {
1450 commands.push(self_command.clone());
1451 self_next = self_it.next();
1452 } else {
1453 commands.push(rhs_command.clone());
1454 rhs_next = rhs_it.next();
1455 }
1456 }
1457 (
1458 VecPatchCommand::Replace(self_pos, _)
1459 | VecPatchCommand::InsertBefore(self_pos, _)
1460 | VecPatchCommand::InsertAfter(self_pos, _),
1461 VecPatchCommand::Replace(rhs_pos, _)
1462 | VecPatchCommand::InsertBefore(rhs_pos, _)
1463 | VecPatchCommand::InsertAfter(rhs_pos, _),
1464 ) => {
1465 if self_pos == rhs_pos {
1466 match (self_command, rhs_command) {
1467 (VecPatchCommand::InsertBefore(_, _), _)
1468 | (_, VecPatchCommand::InsertAfter(_, _)) => {
1469 commands.push(self_command.clone());
1470 self_next = self_it.next();
1471 }
1472 (_, VecPatchCommand::InsertBefore(_, _))
1473 | (VecPatchCommand::InsertAfter(_, _), _) => {
1474 commands.push(rhs_command.clone());
1475 rhs_next = rhs_it.next();
1476 }
1477 _ => panic!("This case should have been reached"),
1478 }
1479 } else if self_pos < rhs_pos {
1480 commands.push(self_command.clone());
1481 self_next = self_it.next();
1482 } else {
1483 commands.push(rhs_command.clone());
1484 rhs_next = rhs_it.next();
1485 }
1486 }
1487 }
1488 }
1489
1490 let remaining_commands = if self_next.is_some() {
1491 std::iter::once(self_next.unwrap()).chain(self_it)
1492 } else {
1493 std::iter::once(rhs_next.unwrap()).chain(self_it)
1494 };
1495 remaining_commands.for_each(|c| commands.push(c.clone()));
1496
1497 Self { commands }
1498 }
1499}
1500
1501impl<T, P> Merge for VecDeepPatch<T, P>
1502where
1503 T: Clone + Patch<P> + From<P>,
1504 P: Clone + Merge,
1505{
1506 fn merge(self, other: Self) -> Self {
1507 if other.commands.len() == 1
1508 && matches!(
1509 other.commands.first(),
1510 Some(VecDeepPatchCommand::ReplaceAll(_))
1511 )
1512 {
1513 return other;
1514 }
1515 if self.commands.len() == 1 {
1516 if let Some(VecDeepPatchCommand::ReplaceAll(self_vec)) = self.commands.first() {
1517 let mut self_vec = self_vec.clone();
1518 self_vec.apply(other);
1519 return VecDeepPatch {
1520 commands: vec![VecDeepPatchCommand::ReplaceAll(self_vec)],
1521 };
1522 }
1523 }
1524
1525 let mut commands: Vec<VecDeepPatchCommand<T, P>> = vec![];
1526
1527 let mut self_it = self.commands.iter();
1528 let mut rhs_it = other.commands.iter();
1529
1530 let mut self_next = self_it.next();
1531 let mut rhs_next = rhs_it.next();
1532
1533 while let (Some(self_command), Some(rhs_command)) = (self_next, rhs_next) {
1534 match (self_command.clone(), rhs_command.clone()) {
1535 (VecDeepPatchCommand::ReplaceAll(_), _)
1536 | (_, VecDeepPatchCommand::ReplaceAll(_)) => {
1537 panic!("Cannot combine a replace all with other commands");
1538 }
1539 (
1540 VecDeepPatchCommand::Append(elements),
1541 VecDeepPatchCommand::Append(rhs_elements),
1542 ) => {
1543 let mut elements = elements;
1546 elements.extend(rhs_elements);
1547 commands.push(VecDeepPatchCommand::Append(elements));
1548 self_next = self_it.next();
1549 rhs_next = rhs_it.next();
1550 }
1551 (self_command, VecDeepPatchCommand::Append(_)) => {
1552 commands.push(self_command);
1553 self_next = self_it.next();
1554 }
1555 (VecDeepPatchCommand::Append(_), rhs_command) => {
1556 commands.push(rhs_command);
1557 rhs_next = rhs_it.next();
1558 }
1559 (
1560 VecDeepPatchCommand::Replace(self_pos, self_val),
1561 VecDeepPatchCommand::Replace(rhs_pos, rhs_val),
1562 ) => {
1563 if self_pos == rhs_pos {
1564 commands.push(VecDeepPatchCommand::Replace(rhs_pos, rhs_val));
1565 self_next = self_it.next();
1566 rhs_next = rhs_it.next();
1567 } else if self_pos < rhs_pos {
1568 commands.push(VecDeepPatchCommand::Replace(self_pos, self_val));
1569 self_next = self_it.next();
1570 } else {
1571 commands.push(VecDeepPatchCommand::Replace(rhs_pos, rhs_val));
1572 rhs_next = rhs_it.next();
1573 }
1574 }
1575 (
1576 VecDeepPatchCommand::Replace(self_pos, self_val),
1577 VecDeepPatchCommand::Patch(rhs_pos, rhs_val),
1578 ) => {
1579 if self_pos == rhs_pos {
1580 let mut val = self_val.clone();
1581 val.apply(rhs_val);
1582 commands.push(VecDeepPatchCommand::Replace(rhs_pos, val));
1583 self_next = self_it.next();
1584 rhs_next = rhs_it.next();
1585 } else if self_pos < rhs_pos {
1586 commands.push(VecDeepPatchCommand::Replace(self_pos, self_val));
1587 self_next = self_it.next();
1588 } else {
1589 commands.push(VecDeepPatchCommand::Patch(rhs_pos, rhs_val));
1590 rhs_next = rhs_it.next();
1591 }
1592 }
1593 (
1594 VecDeepPatchCommand::Patch(self_pos, self_val),
1595 VecDeepPatchCommand::Replace(rhs_pos, rhs_val),
1596 ) => {
1597 if self_pos == rhs_pos {
1598 commands.push(VecDeepPatchCommand::Replace(rhs_pos, rhs_val));
1599 self_next = self_it.next();
1600 rhs_next = rhs_it.next();
1601 } else if self_pos < rhs_pos {
1602 commands.push(VecDeepPatchCommand::Patch(self_pos, self_val));
1603 self_next = self_it.next();
1604 } else {
1605 commands.push(VecDeepPatchCommand::Replace(rhs_pos, rhs_val));
1606 rhs_next = rhs_it.next();
1607 }
1608 }
1609 (
1610 VecDeepPatchCommand::Patch(self_pos, self_val),
1611 VecDeepPatchCommand::Patch(rhs_pos, rhs_val),
1612 ) => {
1613 if self_pos == rhs_pos {
1614 commands.push(VecDeepPatchCommand::Patch(rhs_pos, self_val.merge(rhs_val)));
1615 self_next = self_it.next();
1616 rhs_next = rhs_it.next();
1617 } else if self_pos < rhs_pos {
1618 commands.push(VecDeepPatchCommand::Patch(self_pos, self_val));
1619 self_next = self_it.next();
1620 } else {
1621 commands.push(VecDeepPatchCommand::Patch(rhs_pos, rhs_val));
1622 rhs_next = rhs_it.next();
1623 }
1624 }
1625 (
1626 VecDeepPatchCommand::InsertBefore(self_pos, self_val),
1627 VecDeepPatchCommand::InsertBefore(rhs_pos, mut rhs_val),
1628 )
1629 | (
1630 VecDeepPatchCommand::InsertAfter(self_pos, self_val),
1631 VecDeepPatchCommand::InsertAfter(rhs_pos, mut rhs_val),
1632 ) => {
1633 if self_pos == rhs_pos {
1634 rhs_val.extend(self_val);
1638 commands.push(rhs_command.clone());
1639 self_next = self_it.next();
1640 rhs_next = rhs_it.next();
1641 } else if self_pos < rhs_pos {
1642 commands.push(self_command.clone());
1643 self_next = self_it.next();
1644 } else {
1645 commands.push(rhs_command.clone());
1646 rhs_next = rhs_it.next();
1647 }
1648 }
1649 (
1650 VecDeepPatchCommand::Replace(_, _)
1651 | VecDeepPatchCommand::Patch(_, _)
1652 | VecDeepPatchCommand::InsertBefore(_, _)
1653 | VecDeepPatchCommand::InsertAfter(_, _),
1654 VecDeepPatchCommand::Replace(_, _)
1655 | VecDeepPatchCommand::Patch(_, _)
1656 | VecDeepPatchCommand::InsertBefore(_, _)
1657 | VecDeepPatchCommand::InsertAfter(_, _),
1658 ) => {
1659 if sort_commands(self_command, rhs_command) == Ordering::Less {
1660 commands.push(self_command.clone());
1661 self_next = self_it.next();
1662 } else {
1663 commands.push(rhs_command.clone());
1664 rhs_next = rhs_it.next();
1665 }
1666 }
1667 }
1668 }
1669
1670 let remaining_commands = if self_next.is_some() {
1671 std::iter::once(self_next.unwrap()).chain(self_it)
1672 } else {
1673 std::iter::once(rhs_next.unwrap()).chain(self_it)
1674 };
1675 remaining_commands.for_each(|c| commands.push(c.clone()));
1676
1677 Self { commands }
1678 }
1679}
1680
1681impl<K, V> Merge for HashMapPatch<K, V>
1682where
1683 K: Clone + Eq + Hash,
1684 V: Clone,
1685{
1686 fn merge(self, other: Self) -> Self {
1687 let mut patches = self.patches;
1688 for (key, value) in other.patches {
1689 match value {
1690 Some(value) => {
1691 patches.insert(key, Some(value));
1692 }
1693 None => {
1694 patches.remove(&key);
1695 }
1696 }
1697 }
1698 HashMapPatch { patches }
1699 }
1700}
1701
1702impl<K, V> Merge for HashMapDeepPatch<K, V>
1703where
1704 K: Clone + Eq + Hash,
1705 V: Clone + Merge,
1706{
1707 fn merge(mut self, other: Self) -> Self {
1708 for (key, value) in other.patches {
1709 match value {
1710 Some(value) => match self.patches.get_mut(&key) {
1711 Some(Some(patch)) => {
1712 *patch = patch.clone().merge(value);
1713 }
1714 _ => {
1715 self.patches.insert(key, Some(value));
1716 }
1717 },
1718 None => {
1719 self.patches.remove(&key);
1720 }
1721 }
1722 }
1723 self
1724 }
1725}
1726
1727#[cfg(not(feature = "strict"))]
1728impl<T> Merge for NestedMap<T>
1729where
1730 T: Clone,
1731{
1732 fn merge(mut self, other: Self) -> Self {
1733 let mut flatten = other.clone();
1734 flatten.flatten();
1735 self.flatten();
1736 for (key, value) in flatten.0 {
1737 self.0.insert(key.clone(), value.clone());
1738 }
1739 self
1740 }
1741}
1742
1743#[cfg(test)]
1746mod test {
1747 use super::*;
1748 use pretty_assertions_sorted::assert_eq_sorted;
1749
1750 #[cfg(feature = "permissive")]
1751 mod parsable_struct {
1752 use super::*;
1753
1754 #[test]
1755 fn deserialize_basic_user() {
1756 let user: ParsableStruct<UserPatch> = serde_yaml::from_str("user").unwrap();
1757
1758 assert_eq_sorted!(
1759 user,
1760 ParsableStruct(UserPatch {
1761 user: Some("user".into()),
1762 group: Some(None),
1763 })
1764 );
1765 }
1766
1767 #[test]
1768 fn deserialize_user_error_wrong_username() {
1769 let res = serde_yaml::from_str::<ParsableStruct<UserPatch>>("user*name");
1770
1771 assert!(res.is_err());
1772
1773 assert_eq_sorted!(
1774 res.unwrap_err().to_string(),
1775 "Error while parsing a permissive struct: Not matching chown pattern"
1776 );
1777 }
1778
1779 #[test]
1780 fn deserialize_stage_with_invalid_user() {
1781 let res = serde_yaml::from_str::<StagePatch>("user: user*name");
1782
1783 assert!(res.is_err());
1784
1785 assert_eq_sorted!(
1786 res.unwrap_err().to_string(),
1787 "user: Error while parsing a permissive struct: Not matching chown pattern at line 1 column 7"
1788 );
1789 }
1790
1791 #[ignore = "Not managed yet by serde because of multilevel flatten: https://serde.rs/field-attrs.html#flatten"]
1792 #[test]
1793 fn deserialize_dofigen_with_invalid_user() {
1794 let res = serde_yaml::from_str::<DofigenPatch>("user: user*name");
1795
1796 assert!(res.is_err());
1797
1798 assert_eq_sorted!(
1799 res.unwrap_err().to_string(),
1800 "user: Error while parsing a permissive struct: Not matching chown pattern at line 1 column 7"
1801 );
1802 }
1803 }
1804
1805 mod vec_patch {
1806 use super::*;
1807 use serde::Deserialize;
1808 use struct_patch::Patch;
1809
1810 #[derive(Debug, Clone, PartialEq, Patch, Default)]
1811 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
1812 struct TestStruct {
1813 pub name: String,
1814 #[patch(name = "Option<SubTestStructPatch>")]
1815 pub sub: Option<SubTestStruct>,
1816 }
1817
1818 #[derive(Debug, Clone, PartialEq, Patch, Default)]
1819 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
1820 struct SubTestStruct {
1821 #[patch(name = "VecPatch<String>")]
1822 pub list: Vec<String>,
1823 pub num: Option<u32>,
1824 }
1825
1826 impl From<TestStructPatch> for TestStruct {
1827 fn from(patch: TestStructPatch) -> Self {
1828 let mut sub = Self::default();
1829 sub.apply(patch);
1830 sub
1831 }
1832 }
1833
1834 impl From<SubTestStructPatch> for SubTestStruct {
1835 fn from(patch: SubTestStructPatch) -> Self {
1836 let mut sub = Self::default();
1837 sub.apply(patch);
1838 sub
1839 }
1840 }
1841
1842 #[test]
1843 fn test_simple_patch() {
1844 let base = r#"
1845 name: patch1
1846 sub:
1847 list:
1848 - item1
1849 - item2
1850 num: 42
1851 "#;
1852
1853 let patch = r#"
1854 name: patch2
1855 sub:
1856 num: 43
1857 "#;
1858
1859 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
1860 .unwrap()
1861 .into();
1862 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
1863
1864 base_data.apply(patch_data);
1865
1866 assert_eq_sorted!(
1867 base_data,
1868 TestStruct {
1869 name: "patch2".into(),
1870 sub: Some(SubTestStruct {
1871 list: vec!["item1".into(), "item2".into()],
1872 num: Some(43)
1873 })
1874 }
1875 );
1876 }
1877
1878 #[test]
1879 fn test_vec_replace() {
1880 let base = r#"
1881 name: patch1
1882 sub:
1883 list:
1884 - item1
1885 - item2
1886 num: 42
1887 "#;
1888
1889 let patch = r#"
1890 sub:
1891 list:
1892 - item3
1893 - item4
1894 "#;
1895
1896 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
1897 .unwrap()
1898 .into();
1899 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
1900
1901 base_data.apply(patch_data);
1902
1903 assert_eq_sorted!(
1904 base_data,
1905 TestStruct {
1906 name: "patch1".into(),
1907 sub: Some(SubTestStruct {
1908 list: vec!["item3".into(), "item4".into()],
1909 num: Some(42)
1910 })
1911 }
1912 );
1913 }
1914
1915 #[test]
1916 fn test_vec_append_list_patch() {
1917 let base = r#"
1918 name: patch1
1919 sub:
1920 list:
1921 - item1
1922 - item2
1923 num: 42
1924 "#;
1925
1926 let patch = r#"
1927 sub:
1928 list:
1929 +:
1930 - item3
1931 - item4
1932 "#;
1933
1934 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
1935 .unwrap()
1936 .into();
1937 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
1938
1939 base_data.apply(patch_data);
1940
1941 assert_eq_sorted!(
1942 base_data,
1943 TestStruct {
1944 name: "patch1".into(),
1945 sub: Some(SubTestStruct {
1946 list: vec![
1947 "item1".into(),
1948 "item2".into(),
1949 "item3".into(),
1950 "item4".into()
1951 ],
1952 num: Some(42)
1953 })
1954 }
1955 );
1956 }
1957
1958 #[cfg(feature = "permissive")]
1959 #[test]
1960 fn test_vec_append_one_patch() {
1961 let base = r#"
1962 name: patch1
1963 sub:
1964 list:
1965 - item1
1966 - item2
1967 num: 42
1968 "#;
1969
1970 let patch = r#"
1971 sub:
1972 list:
1973 +: item3
1974 "#;
1975
1976 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
1977 .unwrap()
1978 .into();
1979 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
1980
1981 base_data.apply(patch_data);
1982
1983 assert_eq_sorted!(
1984 base_data,
1985 TestStruct {
1986 name: "patch1".into(),
1987 sub: Some(SubTestStruct {
1988 list: vec!["item1".into(), "item2".into(), "item3".into()],
1989 num: Some(42)
1990 })
1991 }
1992 );
1993 }
1994
1995 #[test]
1996 fn test_vec_replace_patch() {
1997 let base = r#"
1998 name: patch1
1999 sub:
2000 list:
2001 - item1
2002 - item2
2003 - item3
2004 - item4
2005 num: 42
2006 "#;
2007
2008 let patch = r#"
2009 sub:
2010 list:
2011 1: item5
2012 3: item6
2013 "#;
2014
2015 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2016 .unwrap()
2017 .into();
2018 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2019
2020 base_data.apply(patch_data);
2021
2022 assert_eq_sorted!(
2023 base_data,
2024 TestStruct {
2025 name: "patch1".into(),
2026 sub: Some(SubTestStruct {
2027 list: vec![
2028 "item1".into(),
2029 "item5".into(),
2030 "item3".into(),
2031 "item6".into()
2032 ],
2033 num: Some(42)
2034 })
2035 }
2036 );
2037 }
2038
2039 #[test]
2040 fn test_vec_insert_before_patch() {
2041 let base = r#"
2042 name: patch1
2043 sub:
2044 list:
2045 - item1
2046 - item2
2047 - item3
2048 - item4
2049 num: 42
2050 "#;
2051
2052 let patch = r#"
2053 sub:
2054 list:
2055 "+1":
2056 - item5
2057 - item6
2058 "#;
2059
2060 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2061 .unwrap()
2062 .into();
2063 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2064
2065 base_data.apply(patch_data);
2066
2067 assert_eq_sorted!(
2068 base_data,
2069 TestStruct {
2070 name: "patch1".into(),
2071 sub: Some(SubTestStruct {
2072 list: vec![
2073 "item1".into(),
2074 "item5".into(),
2075 "item6".into(),
2076 "item2".into(),
2077 "item3".into(),
2078 "item4".into()
2079 ],
2080 num: Some(42)
2081 })
2082 }
2083 );
2084 }
2085
2086 #[test]
2087 fn test_vec_insert_after_patch() {
2088 let base = r#"
2089 name: patch1
2090 sub:
2091 list:
2092 - item1
2093 - item2
2094 - item3
2095 - item4
2096 num: 42
2097 "#;
2098
2099 let patch = r#"
2100 sub:
2101 list:
2102 1+:
2103 - item5
2104 - item6
2105 "#;
2106
2107 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2108 .unwrap()
2109 .into();
2110 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2111
2112 base_data.apply(patch_data);
2113
2114 assert_eq_sorted!(
2115 base_data,
2116 TestStruct {
2117 name: "patch1".into(),
2118 sub: Some(SubTestStruct {
2119 list: vec![
2120 "item1".into(),
2121 "item2".into(),
2122 "item5".into(),
2123 "item6".into(),
2124 "item3".into(),
2125 "item4".into()
2126 ],
2127 num: Some(42)
2128 })
2129 }
2130 );
2131 }
2132
2133 #[test]
2134 fn test_vec_many_operations_patch() {
2135 let base = r#"
2136 name: patch1
2137 sub:
2138 list:
2139 - item1
2140 - item2
2141 - item3
2142 - item4
2143 num: 42
2144 "#;
2145
2146 let patch = r#"
2147 sub:
2148 list:
2149 "+2":
2150 - item6
2151 1+:
2152 - item5
2153 +:
2154 - item7
2155 0: item0
2156 "#;
2157
2158 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2159 .unwrap()
2160 .into();
2161 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2162
2163 base_data.apply(patch_data);
2164
2165 assert_eq_sorted!(
2166 base_data,
2167 TestStruct {
2168 name: "patch1".into(),
2169 sub: Some(SubTestStruct {
2170 list: vec![
2171 "item0".into(),
2172 "item2".into(),
2173 "item5".into(),
2174 "item6".into(),
2175 "item3".into(),
2176 "item4".into(),
2177 "item7".into()
2178 ],
2179 num: Some(42)
2180 })
2181 }
2182 );
2183 }
2184 }
2185
2186 mod vec_deep_patch {
2187 use super::*;
2188 use serde::Deserialize;
2189 use struct_patch::Patch;
2190
2191 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2192 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2193 struct TestStruct {
2194 pub name: String,
2195 #[patch(name = "VecDeepPatch<SubTestStruct, SubTestStructPatch>")]
2196 pub subs: Vec<SubTestStruct>,
2197 }
2198
2199 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2200 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2201 struct SubTestStruct {
2202 pub name: String,
2203 pub num: u32,
2204 }
2205
2206 impl From<TestStructPatch> for TestStruct {
2207 fn from(patch: TestStructPatch) -> Self {
2208 let mut sub = Self::default();
2209 sub.apply(patch);
2210 sub
2211 }
2212 }
2213
2214 impl From<SubTestStructPatch> for SubTestStruct {
2215 fn from(patch: SubTestStructPatch) -> Self {
2216 let mut sub = Self::default();
2217 sub.apply(patch);
2218 sub
2219 }
2220 }
2221
2222 #[test]
2223 fn test_simple_patch() {
2224 let base = r#"
2225 name: patch1
2226 subs:
2227 - name: sub1
2228 num: 1
2229 - name: sub2
2230 num: 2
2231 "#;
2232
2233 let patch = r#"
2234 name: patch2
2235 "#;
2236
2237 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2238 .unwrap()
2239 .into();
2240 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2241
2242 base_data.apply(patch_data);
2243
2244 assert_eq_sorted!(
2245 base_data,
2246 TestStruct {
2247 name: "patch2".into(),
2248 subs: vec![
2249 SubTestStruct {
2250 name: "sub1".into(),
2251 num: 1
2252 },
2253 SubTestStruct {
2254 name: "sub2".into(),
2255 num: 2
2256 }
2257 ],
2258 }
2259 );
2260 }
2261
2262 #[test]
2263 fn test_vec_replace() {
2264 let base = r#"
2265 name: patch1
2266 subs:
2267 - name: sub1
2268 num: 1
2269 - name: sub2
2270 num: 2
2271 "#;
2272
2273 let patch = r#"
2274 subs:
2275 - name: sub3
2276 num: 3
2277 - name: sub4
2278 num: 4
2279 "#;
2280
2281 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2282 .unwrap()
2283 .into();
2284 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2285
2286 base_data.apply(patch_data);
2287
2288 assert_eq_sorted!(
2289 base_data,
2290 TestStruct {
2291 name: "patch1".into(),
2292 subs: vec![
2293 SubTestStruct {
2294 name: "sub3".into(),
2295 num: 3
2296 },
2297 SubTestStruct {
2298 name: "sub4".into(),
2299 num: 4
2300 }
2301 ]
2302 }
2303 );
2304 }
2305
2306 #[test]
2307 fn test_vec_append_list_patch() {
2308 let base = r#"
2309 name: patch1
2310 subs:
2311 - name: sub1
2312 num: 1
2313 - name: sub2
2314 num: 2
2315 "#;
2316
2317 let patch = r#"
2318 subs:
2319 +:
2320 - name: sub3
2321 num: 3
2322 - name: sub4
2323 num: 4
2324 "#;
2325
2326 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2327 .unwrap()
2328 .into();
2329 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2330
2331 base_data.apply(patch_data);
2332
2333 assert_eq_sorted!(
2334 base_data,
2335 TestStruct {
2336 name: "patch1".into(),
2337 subs: vec![
2338 SubTestStruct {
2339 name: "sub1".into(),
2340 num: 1
2341 },
2342 SubTestStruct {
2343 name: "sub2".into(),
2344 num: 2
2345 },
2346 SubTestStruct {
2347 name: "sub3".into(),
2348 num: 3
2349 },
2350 SubTestStruct {
2351 name: "sub4".into(),
2352 num: 4
2353 }
2354 ]
2355 }
2356 );
2357 }
2358
2359 #[cfg(feature = "permissive")]
2360 #[test]
2361 fn test_vec_append_one_patch() {
2362 let base = r#"
2363 name: patch1
2364 subs:
2365 - name: sub1
2366 num: 1
2367 - name: sub2
2368 num: 2
2369 "#;
2370
2371 let patch = r#"
2372 subs:
2373 +:
2374 name: sub3
2375 num: 3
2376 "#;
2377
2378 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2379 .unwrap()
2380 .into();
2381 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2382
2383 base_data.apply(patch_data);
2384
2385 assert_eq_sorted!(
2386 base_data,
2387 TestStruct {
2388 name: "patch1".into(),
2389 subs: vec![
2390 SubTestStruct {
2391 name: "sub1".into(),
2392 num: 1
2393 },
2394 SubTestStruct {
2395 name: "sub2".into(),
2396 num: 2
2397 },
2398 SubTestStruct {
2399 name: "sub3".into(),
2400 num: 3
2401 }
2402 ]
2403 }
2404 );
2405 }
2406
2407 #[test]
2408 fn test_vec_replace_patch() {
2409 let base = r#"
2410 name: patch1
2411 subs:
2412 - name: sub1
2413 num: 1
2414 - name: sub2
2415 num: 2
2416 "#;
2417
2418 let patch = r#"
2419 subs:
2420 1:
2421 name: sub3
2422 num: 3
2423 "#;
2424
2425 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2426 .unwrap()
2427 .into();
2428 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2429
2430 base_data.apply(patch_data);
2431
2432 assert_eq_sorted!(
2433 base_data,
2434 TestStruct {
2435 name: "patch1".into(),
2436 subs: vec![
2437 SubTestStruct {
2438 name: "sub1".into(),
2439 num: 1
2440 },
2441 SubTestStruct {
2442 name: "sub3".into(),
2443 num: 3
2444 },
2445 ]
2446 }
2447 );
2448 }
2449
2450 #[test]
2451 fn test_vec_deep_patch() {
2452 let base = r#"
2453 name: patch1
2454 subs:
2455 - name: sub1
2456 num: 1
2457 - name: sub2
2458 num: 2
2459 "#;
2460
2461 let patch = r#"
2462 subs:
2463 0<:
2464 num: 3
2465 "#;
2466
2467 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2468 .unwrap()
2469 .into();
2470 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2471
2472 base_data.apply(patch_data);
2473
2474 assert_eq_sorted!(
2475 base_data,
2476 TestStruct {
2477 name: "patch1".into(),
2478 subs: vec![
2479 SubTestStruct {
2480 name: "sub1".into(),
2481 num: 3
2482 },
2483 SubTestStruct {
2484 name: "sub2".into(),
2485 num: 2
2486 },
2487 ]
2488 }
2489 );
2490 }
2491
2492 #[test]
2493 fn test_vec_insert_before_patch() {
2494 let base = r#"
2495 name: patch1
2496 subs:
2497 - name: sub1
2498 num: 1
2499 - name: sub2
2500 num: 2
2501 - name: sub3
2502 num: 3
2503 - name: sub4
2504 num: 4
2505 "#;
2506
2507 let patch = r#"
2508 subs:
2509 "+1":
2510 - name: sub5
2511 num: 5
2512 - name: sub6
2513 num: 6
2514 "#;
2515
2516 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2517 .unwrap()
2518 .into();
2519 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2520
2521 base_data.apply(patch_data);
2522
2523 assert_eq_sorted!(
2524 base_data,
2525 TestStruct {
2526 name: "patch1".into(),
2527 subs: vec![
2528 SubTestStruct {
2529 name: "sub1".into(),
2530 num: 1
2531 },
2532 SubTestStruct {
2533 name: "sub5".into(),
2534 num: 5
2535 },
2536 SubTestStruct {
2537 name: "sub6".into(),
2538 num: 6
2539 },
2540 SubTestStruct {
2541 name: "sub2".into(),
2542 num: 2
2543 },
2544 SubTestStruct {
2545 name: "sub3".into(),
2546 num: 3
2547 },
2548 SubTestStruct {
2549 name: "sub4".into(),
2550 num: 4
2551 },
2552 ]
2553 }
2554 );
2555 }
2556
2557 #[test]
2558 fn test_vec_insert_after_patch() {
2559 let base = r#"
2560 name: patch1
2561 subs:
2562 - name: sub1
2563 num: 1
2564 - name: sub2
2565 num: 2
2566 - name: sub3
2567 num: 3
2568 - name: sub4
2569 num: 4
2570 "#;
2571
2572 let patch = r#"
2573 subs:
2574 1+:
2575 - name: sub5
2576 num: 5
2577 - name: sub6
2578 num: 6
2579 "#;
2580
2581 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2582 .unwrap()
2583 .into();
2584 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2585
2586 base_data.apply(patch_data);
2587
2588 assert_eq_sorted!(
2589 base_data,
2590 TestStruct {
2591 name: "patch1".into(),
2592 subs: vec![
2593 SubTestStruct {
2594 name: "sub1".into(),
2595 num: 1
2596 },
2597 SubTestStruct {
2598 name: "sub2".into(),
2599 num: 2
2600 },
2601 SubTestStruct {
2602 name: "sub5".into(),
2603 num: 5
2604 },
2605 SubTestStruct {
2606 name: "sub6".into(),
2607 num: 6
2608 },
2609 SubTestStruct {
2610 name: "sub3".into(),
2611 num: 3
2612 },
2613 SubTestStruct {
2614 name: "sub4".into(),
2615 num: 4
2616 },
2617 ]
2618 }
2619 );
2620 }
2621
2622 #[test]
2623 fn test_vec_many_operations_patch() {
2624 let base = r#"
2625 name: patch1
2626 subs:
2627 - name: sub1
2628 num: 1
2629 - name: sub2
2630 num: 2
2631 - name: sub3
2632 num: 3
2633 - name: sub4
2634 num: 4
2635 "#;
2636
2637 let patch = r#"
2638 subs:
2639 "+2":
2640 - name: sub6
2641 num: 6
2642 1+:
2643 - name: sub5
2644 num: 5
2645 +:
2646 - name: sub7
2647 num: 7
2648 0:
2649 name: sub0
2650 num: 0
2651 1<:
2652 num: 1
2653 "#;
2654
2655 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2656 .unwrap()
2657 .into();
2658 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2659
2660 base_data.apply(patch_data);
2661
2662 assert_eq_sorted!(
2663 base_data,
2664 TestStruct {
2665 name: "patch1".into(),
2666 subs: vec![
2667 SubTestStruct {
2668 name: "sub0".into(),
2669 num: 0
2670 },
2671 SubTestStruct {
2672 name: "sub2".into(),
2673 num: 1
2674 },
2675 SubTestStruct {
2676 name: "sub5".into(),
2677 num: 5
2678 },
2679 SubTestStruct {
2680 name: "sub6".into(),
2681 num: 6
2682 },
2683 SubTestStruct {
2684 name: "sub3".into(),
2685 num: 3
2686 },
2687 SubTestStruct {
2688 name: "sub4".into(),
2689 num: 4
2690 },
2691 SubTestStruct {
2692 name: "sub7".into(),
2693 num: 7
2694 },
2695 ]
2696 }
2697 );
2698 }
2699 }
2700
2701 mod hashmap_patch {
2702 use super::*;
2703 use serde::Deserialize;
2704 use struct_patch::Patch;
2705
2706 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2707 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2708 struct TestStruct {
2709 pub name: String,
2710 #[patch(name = "HashMapPatch<String, String>")]
2711 pub subs: HashMap<String, String>,
2712 }
2713
2714 impl From<TestStructPatch> for TestStruct {
2715 fn from(patch: TestStructPatch) -> Self {
2716 let mut sub = Self::default();
2717 sub.apply(patch);
2718 sub
2719 }
2720 }
2721
2722 #[test]
2723 fn test_simple_patch() {
2724 let base = r#"
2725 name: patch1
2726 subs:
2727 sub1: value1
2728 sub2: value2
2729 "#;
2730
2731 let patch = r#"
2732 name: patch2
2733 subs:
2734 sub2: null
2735 sub3: value3
2736 "#;
2737
2738 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2739 .unwrap()
2740 .into();
2741 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2742
2743 base_data.apply(patch_data);
2744
2745 assert_eq_sorted!(
2746 base_data,
2747 TestStruct {
2748 name: "patch2".into(),
2749 subs: HashMap::from([
2750 ("sub1".to_string(), "value1".to_string()),
2751 ("sub3".to_string(), "value3".to_string())
2752 ])
2753 }
2754 );
2755 }
2756 }
2757
2758 mod hashmap_deep_patch {
2759 use super::*;
2760 use serde::Deserialize;
2761 use struct_patch::Patch;
2762
2763 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2764 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2765 struct TestStruct {
2766 pub name: String,
2767 #[patch(name = "HashMapDeepPatch<String, TestSubStructPatch>")]
2768 pub subs: HashMap<String, TestSubStruct>,
2769 }
2770
2771 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2772 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2773 struct TestSubStruct {
2774 pub name: String,
2775 }
2776
2777 impl From<TestStructPatch> for TestStruct {
2778 fn from(patch: TestStructPatch) -> Self {
2779 let mut sub = Self::default();
2780 sub.apply(patch);
2781 sub
2782 }
2783 }
2784
2785 impl From<TestSubStructPatch> for TestSubStruct {
2786 fn from(patch: TestSubStructPatch) -> Self {
2787 let mut sub = Self::default();
2788 sub.apply(patch);
2789 sub
2790 }
2791 }
2792
2793 #[test]
2794 fn test_simple_patch() {
2795 let base = r#"
2796 name: patch1
2797 subs:
2798 sub1:
2799 name: value1
2800 sub2:
2801 name: value2
2802 "#;
2803
2804 let patch = r#"
2805 name: patch2
2806 subs:
2807 sub1:
2808 name: value2
2809 sub2: null
2810 sub3:
2811 name: value3
2812 "#;
2813
2814 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2815 .unwrap()
2816 .into();
2817 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2818
2819 base_data.apply(patch_data);
2820
2821 assert_eq_sorted!(
2822 base_data,
2823 TestStruct {
2824 name: "patch2".into(),
2825 subs: HashMap::from([
2826 (
2827 "sub1".to_string(),
2828 TestSubStruct {
2829 name: "value2".to_string()
2830 }
2831 ),
2832 (
2833 "sub3".to_string(),
2834 TestSubStruct {
2835 name: "value3".to_string()
2836 }
2837 )
2838 ])
2839 }
2840 );
2841 }
2842 }
2843
2844 #[cfg(feature = "permissive")]
2845 mod nested_map {
2846
2847 use super::*;
2848
2849 #[test]
2850 fn test_nested_map_patch() {
2851 let mut base_data: HashMap<String, String> =
2852 HashMap::from([("key1.key2".to_string(), "value2".to_string())]);
2853 let patch_data: NestedMap<String> = NestedMap(HashMap::from([
2854 (
2855 "key1".to_string(),
2856 NestedMapValue::Map(NestedMap(HashMap::from([(
2857 "key2".to_string(),
2858 NestedMapValue::Value("patch 1".to_string()),
2859 )]))),
2860 ),
2861 (
2862 "key1.key3".to_string(),
2863 NestedMapValue::Value("value3".to_string()),
2864 ),
2865 ]));
2866
2867 base_data.apply(patch_data);
2868
2869 assert_eq!(
2870 base_data,
2871 HashMap::from([
2872 ("key1.key2".to_string(), "patch 1".to_string()),
2873 ("key1.key3".to_string(), "value3".to_string())
2874 ])
2875 );
2876 }
2877 }
2878
2879 #[cfg(feature = "permissive")]
2880 mod deserialize {
2881 use super::*;
2882
2883 mod one_or_many {
2884 use super::*;
2885
2886 #[derive(Deserialize, Debug, Clone, PartialEq)]
2887 struct TestStruct {
2888 pub one_or_many: OneOrMany<String>,
2889 }
2890
2891 #[test]
2892 fn one() {
2893 let ret: TestStruct = serde_yaml::from_str("one_or_many: test").unwrap();
2894 assert_eq_sorted!(
2895 ret,
2896 TestStruct {
2897 one_or_many: OneOrMany(vec!["test".into()])
2898 }
2899 )
2900 }
2901
2902 #[test]
2903 fn many() {
2904 let ret: TestStruct = serde_yaml::from_str("one_or_many: [test]").unwrap();
2905 assert_eq_sorted!(
2906 ret,
2907 TestStruct {
2908 one_or_many: OneOrMany(vec!["test".into()])
2909 }
2910 )
2911 }
2912 }
2913
2914 mod optional_one_or_many {
2915 use super::*;
2916
2917 #[derive(Deserialize, Debug, Clone, PartialEq, Default)]
2918 struct TestStruct {
2919 pub test: Option<String>,
2920 pub one_or_many: Option<OneOrMany<String>>,
2921 }
2922
2923 #[test]
2924 fn one() {
2925 let ret: TestStruct = serde_yaml::from_str("one_or_many: test").unwrap();
2926 assert_eq_sorted!(
2927 ret,
2928 TestStruct {
2929 test: None,
2930 one_or_many: Some(OneOrMany(vec!["test".into()]))
2931 }
2932 )
2933 }
2934
2935 #[test]
2936 fn many() {
2937 let ret: TestStruct = serde_yaml::from_str("one_or_many: [test]").unwrap();
2938 assert_eq_sorted!(
2939 ret,
2940 TestStruct {
2941 test: None,
2942 one_or_many: Some(OneOrMany(vec!["test".into()]))
2943 }
2944 )
2945 }
2946
2947 #[test]
2948 fn null() {
2949 let ret: TestStruct = serde_yaml::from_str("one_or_many: null").unwrap();
2950 assert_eq_sorted!(
2951 ret,
2952 TestStruct {
2953 test: None,
2954 one_or_many: None
2955 }
2956 )
2957 }
2958
2959 #[test]
2960 fn absent() {
2961 let ret: TestStruct = serde_yaml::from_str("test: test").unwrap();
2962 assert_eq_sorted!(
2963 ret,
2964 TestStruct {
2965 test: Some("test".into()),
2966 one_or_many: None
2967 }
2968 )
2969 }
2970 }
2971
2972 #[cfg(feature = "permissive")]
2973 mod from_optional_string_or_number {
2974 use super::*;
2975
2976 #[derive(Deserialize, Debug, Clone, PartialEq, Default)]
2977 struct TestStruct {
2978 #[serde(
2979 deserialize_with = "deserialize_from_optional_string_or_number",
2980 default
2981 )]
2982 pub test: Option<Option<String>>,
2983 }
2984
2985 #[test]
2986 fn string() {
2987 let ret: TestStruct = serde_yaml::from_str("test: \"123\"").unwrap();
2988 assert_eq_sorted!(
2989 ret,
2990 TestStruct {
2991 test: Some(Some("123".into()))
2992 }
2993 )
2994 }
2995
2996 #[test]
2997 fn number() {
2998 let ret: TestStruct = serde_yaml::from_str("test: 123").unwrap();
2999 assert_eq_sorted!(
3000 ret,
3001 TestStruct {
3002 test: Some(Some("123".into()))
3003 }
3004 )
3005 }
3006
3007 #[test]
3008 fn null() {
3009 let ret: TestStruct = serde_yaml::from_str("test: null").unwrap();
3010 assert_eq_sorted!(ret, TestStruct { test: Some(None) })
3011 }
3012
3013 #[test]
3014 fn absent() {
3015 let ret: TestStruct = serde_yaml::from_str("").unwrap();
3016 assert_eq_sorted!(ret, TestStruct { test: None })
3017 }
3018 }
3019
3020 mod nested_map {
3021
3022 use super::*;
3023
3024 #[test]
3025 fn test_single_level_map() {
3026 let yaml = r#"
3027 key1: value1
3028 key2: value2
3029 key3:
3030 "#;
3031
3032 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3033
3034 assert_eq!(
3035 result,
3036 NestedMap(HashMap::from([
3037 (
3038 "key1".to_string(),
3039 NestedMapValue::Value("value1".to_string())
3040 ),
3041 (
3042 "key2".to_string(),
3043 NestedMapValue::Value("value2".to_string())
3044 ),
3045 ("key3".to_string(), NestedMapValue::Null)
3046 ]))
3047 );
3048 }
3049
3050 #[test]
3051 fn test_multilevel_map() {
3052 let yaml = r#"
3053 key1:
3054 key2: value
3055 "#;
3056
3057 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3058
3059 assert_eq!(
3060 result,
3061 NestedMap(HashMap::from([(
3062 "key1".to_string(),
3063 NestedMapValue::Map(NestedMap(HashMap::from([(
3064 "key2".to_string(),
3065 NestedMapValue::Value("value".to_string())
3066 )])))
3067 )]))
3068 );
3069 }
3070
3071 #[test]
3072 fn test_equivalent_flattened_map() {
3073 let yaml = r#"
3074 key1.key2: value
3075 "#;
3076
3077 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3078
3079 assert_eq!(
3080 result,
3081 NestedMap(HashMap::from([(
3082 "key1.key2".to_string(),
3083 NestedMapValue::Value("value".to_string())
3084 )]))
3085 );
3086 }
3087
3088 #[test]
3089 fn test_combined_multilevel_and_flattened_map() {
3090 let yaml = r#"
3091 key1:
3092 key2: value2
3093 key1.key3: value3
3094 "#;
3095
3096 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3097
3098 assert_eq!(
3099 result,
3100 NestedMap(HashMap::from([
3101 (
3102 "key1".to_string(),
3103 NestedMapValue::Map(NestedMap(HashMap::from([(
3104 "key2".to_string(),
3105 NestedMapValue::Value("value2".to_string())
3106 )])))
3107 ),
3108 (
3109 "key1.key3".to_string(),
3110 NestedMapValue::Value("value3".to_string())
3111 )
3112 ]))
3113 );
3114 }
3115
3116 #[test]
3117 fn test_empty_map() {
3118 let yaml = r#"
3119 "#;
3120
3121 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3122
3123 assert_eq!(result, NestedMap(HashMap::new()));
3124 }
3125
3126 #[test]
3127 fn test_nested_empty_map() {
3128 let yaml = r#"
3129 key1: {}
3130 "#;
3131
3132 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3133
3134 assert_eq!(
3135 result,
3136 NestedMap(HashMap::from([(
3137 "key1".to_string(),
3138 NestedMapValue::Map(NestedMap(HashMap::new()))
3139 )]))
3140 );
3141 }
3142 }
3143 }
3144}