1use crate::{dofigen_struct::*, Error};
2#[cfg(feature = "json_schema")]
3use schemars::JsonSchema;
4use serde::{de, Deserialize, Deserializer};
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!("Cannot replace element at position {} after another modification on it", pos);
619 }
620 for i in current_position..=pos {
621 current_position = i;
622 position_adaptation += adapted_positions[i];
623 }
624 let adapted_position = current_position + position_adaptation;
625 self[adapted_position] = elements;
626 last_modified_position = pos;
627 }
628 VecPatchCommand::InsertBefore(pos, elements) => {
629 if reset {
630 panic!(
631 "Cannot insert before element at position {} after a reset",
632 pos
633 );
634 }
635 if pos >= initial_len {
636 panic!("Position {} is out of bounds", pos);
637 }
638 for i in current_position..=pos {
639 current_position = i;
640 position_adaptation += adapted_positions[i];
641 }
642 let added = elements.len();
643 let adapted_position = current_position + position_adaptation;
644 self.splice(adapted_position..adapted_position, elements);
645 adapted_positions[pos as usize] += added;
646 }
647 VecPatchCommand::InsertAfter(pos, elements) => {
648 if reset {
649 panic!(
650 "Cannot insert after element at position {} after a reset",
651 pos
652 );
653 }
654 if pos >= initial_len {
655 panic!("Position {} is out of bounds", pos);
656 }
657 for i in current_position..=pos {
658 current_position = i;
659 position_adaptation += adapted_positions[i];
660 }
661 let adapted_position = current_position + position_adaptation + 1;
662 let added = elements.len();
663 self.splice(adapted_position..adapted_position, elements);
664 if pos + 1 < initial_len {
665 adapted_positions[(pos + 1) as usize] = added;
666 } else {
667 adapted_positions.push(added);
668 }
669 }
670 VecPatchCommand::Append(elements) => {
671 self.extend(elements);
672 }
673 }
674 }
675 }
676
677 fn into_patch(self) -> VecPatch<T> {
678 VecPatch {
679 commands: vec![VecPatchCommand::ReplaceAll(self)],
680 }
681 }
682
683 fn into_patch_by_diff(self, _previous_struct: Self) -> VecPatch<T> {
684 todo!()
685 }
690
691 fn new_empty_patch() -> VecPatch<T> {
692 VecPatch { commands: vec![] }
693 }
694}
695
696impl<T, P> Patch<VecDeepPatch<T, P>> for Vec<T>
697where
698 T: Clone + Patch<P> + From<P>,
699 P: Clone,
700{
701 fn apply(&mut self, patch: VecDeepPatch<T, P>) {
702 let mut reset = false;
703 let mut last_modified_position: usize = usize::MAX;
704 let initial_len = self.len();
706 let patch_len = patch.commands.len();
707 let mut adapted_positions: Vec<usize> = vec![0; self.len()];
709 let mut current_position = 0;
711 let mut position_adaptation = 0;
712
713 for command in patch.commands {
714 match command {
715 VecDeepPatchCommand::ReplaceAll(elements) => {
716 if reset {
717 panic!("Cannot replace the list twice");
718 }
719 if patch_len > 1 {
720 panic!("Cannot combine a replace all with other commands");
721 }
722 reset = true;
723 self.clear();
724 self.extend(elements.into_iter());
725 }
726 VecDeepPatchCommand::Replace(pos, element) => {
727 if reset {
728 panic!("Cannot replace element at position {} after a reset", pos);
729 }
730 if pos >= initial_len {
731 panic!("Position {} is out of bounds", pos);
732 }
733 if pos == last_modified_position {
734 panic!("Cannot replace element at position {} after another modification on it", pos);
735 }
736 for i in current_position..=pos {
737 current_position = i;
738 position_adaptation += adapted_positions[i];
739 }
740 let adapted_position = current_position + position_adaptation;
741 self[adapted_position] = element;
742 last_modified_position = pos;
743 }
744 VecDeepPatchCommand::Patch(pos, element) => {
745 if reset {
746 panic!("Cannot patch element at position {} after a reset", pos);
747 }
748 if pos >= initial_len {
749 panic!("Position {} is out of bounds", pos);
750 }
751 if pos == last_modified_position {
752 panic!(
753 "Cannot patch element at position {} after another modification on it",
754 pos
755 );
756 }
757 for i in current_position..=pos {
758 current_position = i;
759 position_adaptation += adapted_positions[i];
760 }
761 let adapted_position = current_position + position_adaptation;
762 self[adapted_position].apply(element);
763 last_modified_position = pos;
764 }
765 VecDeepPatchCommand::InsertBefore(pos, elements) => {
766 if reset {
767 panic!(
768 "Cannot insert before element at position {} after a reset",
769 pos
770 );
771 }
772 if pos >= initial_len {
773 panic!("Position {} is out of bounds", pos);
774 }
775 for i in current_position..=pos {
776 current_position = i;
777 position_adaptation += adapted_positions[i];
778 }
779 let adapted_position = current_position + position_adaptation;
780 let added = elements.len();
781 self.splice(adapted_position..adapted_position, elements);
782 adapted_positions[pos as usize] += added;
783 }
784 VecDeepPatchCommand::InsertAfter(pos, elements) => {
785 if reset {
786 panic!(
787 "Cannot insert after element at position {} after a reset",
788 pos
789 );
790 }
791 if pos >= initial_len {
792 panic!("Position {} is out of bounds", pos);
793 }
794 for i in current_position..=pos {
795 current_position = i;
796 position_adaptation += adapted_positions[i];
797 }
798 let adapted_position = current_position + position_adaptation;
799 let usize_pos = adapted_position + 1;
800 let added = elements.len();
801 self.splice(usize_pos..usize_pos, elements);
802 if pos + 1 < initial_len {
803 adapted_positions[(pos + 1) as usize] = added;
804 } else {
805 adapted_positions.push(added);
806 }
807 }
808 VecDeepPatchCommand::Append(elements) => {
809 self.extend(elements);
810 }
811 }
812 }
813 }
814
815 fn into_patch(self) -> VecDeepPatch<T, P> {
816 VecDeepPatch {
817 commands: vec![VecDeepPatchCommand::ReplaceAll(self)],
818 }
819 }
820
821 fn into_patch_by_diff(self, _previous_struct: Self) -> VecDeepPatch<T, P> {
822 todo!()
823 }
824
825 fn new_empty_patch() -> VecDeepPatch<T, P> {
826 VecDeepPatch { commands: vec![] }
827 }
828}
829
830impl<K, V> Patch<HashMapPatch<K, V>> for HashMap<K, V>
831where
832 K: Clone + Eq + Hash,
833 V: Clone,
834{
835 fn apply(&mut self, patch: HashMapPatch<K, V>) {
836 for (key, value) in patch.patches {
837 match value {
838 Some(value) => {
839 self.insert(key, value);
840 }
841 None => {
842 self.remove(&key);
843 }
844 }
845 }
846 }
847
848 fn into_patch(self) -> HashMapPatch<K, V> {
849 let mut patches = HashMap::new();
850 for (key, value) in self {
851 patches.insert(key, Some(value));
852 }
853 HashMapPatch { patches }
854 }
855
856 fn into_patch_by_diff(self, _previous_struct: Self) -> HashMapPatch<K, V> {
857 todo!()
858 }
859
860 fn new_empty_patch() -> HashMapPatch<K, V> {
861 HashMapPatch {
862 patches: HashMap::new(),
863 }
864 }
865}
866
867impl<K, T, P> Patch<HashMapDeepPatch<K, P>> for HashMap<K, T>
868where
869 K: Clone + Eq + Hash,
870 T: Clone + Patch<P> + From<P>,
871 P: Clone,
872{
873 fn apply(&mut self, patch: HashMapDeepPatch<K, P>) {
874 for (key, value) in patch.patches {
875 match value {
876 Some(value) => {
877 self.insert(key, value.into());
878 }
879 None => {
880 self.remove(&key);
881 }
882 }
883 }
884 }
885
886 fn into_patch(self) -> HashMapDeepPatch<K, P> {
887 let mut patches = HashMap::new();
888 for (key, value) in self {
889 patches.insert(key, Some(value.into_patch()));
890 }
891 HashMapDeepPatch { patches }
892 }
893
894 fn into_patch_by_diff(self, _previous_struct: Self) -> HashMapDeepPatch<K, P> {
895 todo!()
896 }
897
898 fn new_empty_patch() -> HashMapDeepPatch<K, P> {
899 HashMapDeepPatch {
900 patches: HashMap::new(),
901 }
902 }
903}
904
905#[cfg(not(feature = "strict"))]
906impl<T: Clone> From<NestedMap<T>> for HashMap<String, Option<T>> {
907 fn from(value: NestedMap<T>) -> Self {
908 let mut value = value.clone();
909 value.flatten();
910 return value
911 .0
912 .into_iter()
913 .map(|(key, value)| {
914 (
915 key,
916 match value {
917 NestedMapValue::Value(value) => Some(value),
918 NestedMapValue::Map(_) => unreachable!(),
919 NestedMapValue::Null => None,
920 },
921 )
922 })
923 .collect();
924 }
925}
926
927#[cfg(not(feature = "strict"))]
928impl<T> Patch<NestedMap<T>> for HashMap<String, T>
929where
930 T: Clone,
931{
932 fn apply(&mut self, patch: NestedMap<T>) {
933 let flatten: HashMap<String, Option<T>> = patch.into();
934 flatten.into_iter().for_each(|(key, opt)| {
935 if let Some(value) = opt {
936 self.insert(key, value);
937 } else {
938 self.remove(&key);
939 }
940 });
941 }
942
943 fn into_patch(self) -> NestedMap<T> {
944 NestedMap(
945 self.into_iter()
946 .map(|(key, value)| (key.clone(), NestedMapValue::Value(value)))
947 .collect(),
948 )
949 }
950
951 fn into_patch_by_diff(self, _previous_struct: Self) -> NestedMap<T> {
952 todo!()
953 }
954
955 fn new_empty_patch() -> NestedMap<T> {
956 NestedMap(HashMap::new())
957 }
958}
959
960#[cfg(feature = "permissive")]
963impl<'de, T> Deserialize<'de> for ParsableStruct<T>
964where
965 T: FromStr<Err = serde::de::value::Error> + Sized + Deserialize<'de>,
966{
967 fn deserialize<D>(deserializer: D) -> Result<ParsableStruct<T>, D::Error>
968 where
969 D: Deserializer<'de>,
970 {
971 struct PermissiveStructVisitor<T>(Option<T>);
972
973 impl<'de, T> de::Visitor<'de> for PermissiveStructVisitor<T>
974 where
975 T: Deserialize<'de> + FromStr<Err = serde::de::value::Error>,
976 {
977 type Value = T;
978
979 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
980 formatter.write_str("a number, a string or a map")
981 }
982
983 fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
984 where
985 E: de::Error,
986 {
987 self.visit_str(v.to_string().as_str())
988 }
989
990 fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
991 where
992 E: de::Error,
993 {
994 self.visit_str(v.to_string().as_str())
995 }
996
997 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
998 where
999 E: de::Error,
1000 {
1001 self.visit_str(v.to_string().as_str())
1002 }
1003
1004 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
1005 where
1006 E: de::Error,
1007 {
1008 self.visit_str(v.to_string().as_str())
1009 }
1010
1011 fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
1012 where
1013 E: de::Error,
1014 {
1015 self.visit_str(v.to_string().as_str())
1016 }
1017
1018 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
1019 where
1020 E: de::Error,
1021 {
1022 self.visit_str(v.to_string().as_str())
1023 }
1024
1025 fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
1026 where
1027 E: de::Error,
1028 {
1029 self.visit_str(v.to_string().as_str())
1030 }
1031
1032 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
1033 where
1034 E: de::Error,
1035 {
1036 self.visit_str(v.to_string().as_str())
1037 }
1038
1039 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
1040 where
1041 E: de::Error,
1042 {
1043 self.visit_str(v.to_string().as_str())
1044 }
1045
1046 fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
1047 where
1048 E: de::Error,
1049 {
1050 self.visit_str(v.to_string().as_str())
1051 }
1052
1053 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1054 where
1055 E: de::Error,
1056 {
1057 v.parse().map_err(|err| {
1058 E::custom(format!("Error while parsing a permissive struct: {}", err))
1059 })
1060 }
1061
1062 fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
1063 where
1064 A: de::MapAccess<'de>,
1065 {
1066 Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))
1067 }
1068 }
1069
1070 let visitor: PermissiveStructVisitor<T> = PermissiveStructVisitor(None);
1071
1072 deserializer.deserialize_any(visitor).map(ParsableStruct)
1073 }
1074}
1075
1076impl<'de, T> Deserialize<'de> for VecPatchCommandMap<T>
1077where
1078 T: Clone + Deserialize<'de>,
1079{
1080 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1081 where
1082 D: Deserializer<'de>,
1083 {
1084 let commands: Vec<VecDeepPatchCommand<T, T>> =
1085 deserialize_vec_patch_commands(deserializer)?;
1086 Ok(VecPatchCommandMap {
1087 commands: commands
1088 .iter()
1089 .map(|c| c.clone().try_into().map_err(de::Error::custom))
1090 .collect::<Result<Vec<_>, _>>()?,
1091 })
1092 }
1093}
1094
1095impl<'de, T, P> Deserialize<'de> for VecDeepPatchCommandMap<T, P>
1096where
1097 T: Clone + From<P>,
1098 P: Clone + Deserialize<'de>,
1099{
1100 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1101 where
1102 D: Deserializer<'de>,
1103 {
1104 Ok(VecDeepPatchCommandMap {
1105 commands: deserialize_vec_patch_commands(deserializer)?,
1106 })
1107 }
1108}
1109
1110fn deserialize_vec_patch_commands<'de, D, T, P>(
1111 deserializer: D,
1112) -> Result<Vec<VecDeepPatchCommand<T, P>>, D::Error>
1113where
1114 D: Deserializer<'de>,
1115 T: Clone + From<P>,
1116 P: Clone + Deserialize<'de>,
1117{
1118 struct VecDeepPatchCommandsVisitor<T, P>(PhantomData<fn() -> BTreeMap<T, P>>);
1119
1120 #[cfg(feature = "permissive")]
1121 fn map_vec<T, P>(patch: OneOrMany<P>) -> Vec<T>
1122 where
1123 T: Clone + From<P>,
1124 P: Clone,
1125 {
1126 patch.iter().map(|p| p.clone().into()).collect()
1127 }
1128
1129 #[cfg(not(feature = "permissive"))]
1130 fn map_vec<T, P>(patch: Vec<P>) -> Vec<T>
1131 where
1132 T: Clone + From<P>,
1133 P: Clone,
1134 {
1135 patch.iter().map(|p| p.clone().into()).collect()
1136 }
1137
1138 impl<'de, T, P> de::Visitor<'de> for VecDeepPatchCommandsVisitor<T, P>
1139 where
1140 T: Clone + From<P>,
1141 P: Clone + Deserialize<'de>,
1142 {
1143 type Value = Vec<VecDeepPatchCommand<T, P>>;
1144
1145 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1146 formatter.write_str("a map")
1147 }
1148
1149 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1150 where
1151 A: de::MapAccess<'de>,
1152 {
1153 let mut commands = vec![];
1154
1155 while let Some(key) = map.next_key()? {
1156 match key {
1157 StringOrNumber::String(key) => match key.as_str() {
1158 "_" => {
1159 commands
1160 .push(VecDeepPatchCommand::ReplaceAll(map_vec(map.next_value()?)));
1161 }
1162 "+" => {
1163 commands.push(VecDeepPatchCommand::Append(map_vec(map.next_value()?)));
1164 }
1165 key => {
1166 if key.starts_with('+') {
1167 let pos = key[1..key.len()].parse::<usize>().unwrap();
1168 commands.push(VecDeepPatchCommand::InsertBefore(
1169 pos,
1170 map_vec(map.next_value()?),
1171 ));
1172 } else if key.ends_with('+') {
1173 let pos = key[..key.len() - 1].parse::<usize>().unwrap();
1174 commands.push(VecDeepPatchCommand::InsertAfter(
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::Patch(pos, map.next_value()?));
1181 } else {
1182 let value: P = map.next_value()?;
1183 let pos = key.parse::<usize>().unwrap();
1184 commands.push(VecDeepPatchCommand::Replace(pos, value.into()));
1185 }
1186 }
1187 },
1188 StringOrNumber::Number(pos) => {
1189 let value: P = map.next_value()?;
1190 commands.push(VecDeepPatchCommand::Replace(pos, value.into()));
1191 }
1192 }
1193 }
1194
1195 commands.sort_by(sort_commands);
1197
1198 Ok(commands)
1199 }
1200 }
1201
1202 let visitor: VecDeepPatchCommandsVisitor<T, P> = VecDeepPatchCommandsVisitor(PhantomData);
1203
1204 deserializer.deserialize_any(visitor)
1205}
1206
1207#[cfg(feature = "permissive")]
1208pub(crate) fn deserialize_from_optional_string_or_number<'de, D>(
1209 deserializer: D,
1210) -> Result<Option<Option<String>>, D::Error>
1211where
1212 D: Deserializer<'de>,
1213{
1214 let val: Option<StringOrNumber> = Deserialize::deserialize(deserializer)?;
1215
1216 Ok(Some(val.map(|val| match val {
1217 StringOrNumber::String(s) => s,
1218 StringOrNumber::Number(n) => n.to_string(),
1219 })))
1220}
1221
1222fn sort_commands<T, P>(a: &VecDeepPatchCommand<T, P>, b: &VecDeepPatchCommand<T, P>) -> Ordering
1223where
1224 T: Clone + From<P>,
1225 P: Clone,
1226{
1227 match (a, b) {
1228 (VecDeepPatchCommand::ReplaceAll(_), _) => std::cmp::Ordering::Less,
1230 (_, VecDeepPatchCommand::ReplaceAll(_)) => std::cmp::Ordering::Greater,
1231 (VecDeepPatchCommand::Append(_), _) => std::cmp::Ordering::Greater,
1233 (_, VecDeepPatchCommand::Append(_)) => std::cmp::Ordering::Less,
1234 (VecDeepPatchCommand::InsertBefore(a, _), VecDeepPatchCommand::InsertBefore(b, _))
1236 | (
1237 VecDeepPatchCommand::Replace(a, _) | VecDeepPatchCommand::Patch(a, _),
1238 VecDeepPatchCommand::Replace(b, _) | VecDeepPatchCommand::Patch(b, _),
1239 )
1240 | (VecDeepPatchCommand::InsertAfter(a, _), VecDeepPatchCommand::InsertAfter(b, _)) => {
1241 a.cmp(b)
1242 }
1243 (
1249 VecDeepPatchCommand::InsertBefore(a, _),
1250 VecDeepPatchCommand::Replace(b, _)
1251 | VecDeepPatchCommand::Patch(b, _)
1252 | VecDeepPatchCommand::InsertAfter(b, _),
1253 )
1254 | (
1255 VecDeepPatchCommand::Replace(a, _) | VecDeepPatchCommand::Patch(a, _),
1256 VecDeepPatchCommand::InsertAfter(b, _),
1257 ) => match a.cmp(b) {
1258 std::cmp::Ordering::Equal => std::cmp::Ordering::Less,
1259 other => other,
1260 },
1261 (
1262 VecDeepPatchCommand::Replace(a, _)
1263 | VecDeepPatchCommand::Patch(a, _)
1264 | VecDeepPatchCommand::InsertAfter(a, _),
1265 VecDeepPatchCommand::InsertBefore(b, _),
1266 )
1267 | (
1268 VecDeepPatchCommand::InsertAfter(a, _),
1269 VecDeepPatchCommand::Replace(b, _) | VecDeepPatchCommand::Patch(b, _),
1270 ) => match a.cmp(b) {
1271 std::cmp::Ordering::Equal => std::cmp::Ordering::Greater,
1272 other => other,
1273 },
1274 }
1275}
1276
1277macro_rules! merge_option_patch {
1281 ($opt_a: expr, $opt_b: expr) => {
1282 match ($opt_a, $opt_b) {
1283 (Some(a), Some(b)) => Some(a.merge(b)),
1284 (Some(a), None) => Some(a),
1285 (None, Some(b)) => Some(b),
1286 (None, None) => None,
1287 }
1288 };
1289}
1290
1291impl Merge for FromContextPatch {
1292 fn merge(self, other: Self) -> Self {
1293 match (self, other) {
1294 (Self::FromImage(a), Self::FromImage(b)) => Self::FromImage(a.merge(b)),
1295 (_, b) => b,
1296 }
1297 }
1298}
1299
1300impl Merge for CopyResourcePatch {
1301 fn merge(self, other: Self) -> Self {
1302 match (self, other) {
1303 (Self::Copy(a), Self::Copy(b)) => Self::Copy(a.merge(b)),
1304 (Self::Copy(a), Self::Unknown(b)) => {
1305 let mut a = a;
1306 a.options = merge_option_patch!(a.options, b.options);
1307 Self::Copy(a)
1308 }
1309 (Self::Unknown(a), Self::Copy(b)) => {
1310 let mut b = b;
1311 b.options = merge_option_patch!(a.options, b.options);
1312 Self::Copy(b)
1313 }
1314 (Self::Add(a), Self::Add(b)) => Self::Add(a.merge(b)),
1315 (Self::Add(a), Self::Unknown(b)) => {
1316 let mut a = a;
1317 a.options = merge_option_patch!(a.options, b.options);
1318 Self::Add(a)
1319 }
1320 (Self::Unknown(a), Self::Add(b)) => {
1321 let mut b = b;
1322 b.options = merge_option_patch!(a.options, b.options);
1323 Self::Add(b)
1324 }
1325 (Self::AddGitRepo(a), Self::AddGitRepo(b)) => Self::AddGitRepo(a.merge(b)),
1326 (Self::AddGitRepo(a), Self::Unknown(b)) => {
1327 let mut a = a;
1328 a.options = merge_option_patch!(a.options, b.options);
1329 Self::AddGitRepo(a)
1330 }
1331 (Self::Unknown(a), Self::AddGitRepo(b)) => {
1332 let mut b = b;
1333 b.options = merge_option_patch!(a.options, b.options);
1334 Self::AddGitRepo(b)
1335 }
1336 (Self::Unknown(a), Self::Unknown(b)) => Self::Unknown(a.merge(b)),
1337 (a, b) => panic!("Can't merge {:?} and {:?}", a, b),
1338 }
1339 }
1340}
1341
1342impl Merge for UnknownPatch {
1343 fn merge(self, other: Self) -> Self {
1344 Self {
1345 options: merge_option_patch!(self.options, other.options),
1346 exclude: merge_option_patch!(self.exclude, other.exclude),
1347 }
1348 }
1349}
1350
1351#[cfg(feature = "permissive")]
1352impl<T> Merge for ParsableStruct<T>
1353where
1354 T: Clone + FromStr + Merge,
1355{
1356 fn merge(self, other: Self) -> Self {
1357 ParsableStruct(self.0.merge(other.0))
1358 }
1359}
1360
1361impl<T> Merge for VecPatch<T>
1362where
1363 T: Clone,
1364{
1365 fn merge(self, other: Self) -> Self {
1366 if other.commands.len() == 1
1367 && matches!(other.commands.first(), Some(VecPatchCommand::ReplaceAll(_)))
1368 {
1369 return other;
1370 }
1371 if self.commands.len() == 1 {
1372 if let Some(VecPatchCommand::ReplaceAll(self_vec)) = self.commands.first() {
1373 let mut self_vec = self_vec.clone();
1374 self_vec.apply(other);
1375 return VecPatch {
1376 commands: vec![VecPatchCommand::ReplaceAll(self_vec)],
1377 };
1378 }
1379 }
1380
1381 let mut commands: Vec<VecPatchCommand<T>> = vec![];
1382
1383 let mut self_it = self.commands.iter();
1384 let mut rhs_it = other.commands.iter();
1385
1386 let mut self_next = self_it.next();
1387 let mut rhs_next = rhs_it.next();
1388
1389 while let (Some(self_command), Some(rhs_command)) = (self_next, rhs_next) {
1390 match (self_command.clone(), rhs_command.clone()) {
1391 (VecPatchCommand::ReplaceAll(_), _) | (_, VecPatchCommand::ReplaceAll(_)) => {
1392 panic!("Cannot combine a replace all with other commands");
1393 }
1394 (VecPatchCommand::Append(elements), VecPatchCommand::Append(rhs_elements)) => {
1395 let mut elements = elements;
1398 elements.extend(rhs_elements);
1399 commands.push(VecPatchCommand::Append(elements));
1400 self_next = self_it.next();
1401 rhs_next = rhs_it.next();
1402 }
1403 (self_command, VecPatchCommand::Append(_)) => {
1404 commands.push(self_command);
1405 self_next = self_it.next();
1406 }
1407 (VecPatchCommand::Append(_), rhs_command) => {
1408 commands.push(rhs_command);
1409 rhs_next = rhs_it.next();
1410 }
1411 (
1412 VecPatchCommand::Replace(self_pos, self_val),
1413 VecPatchCommand::Replace(rhs_pos, rhs_val),
1414 ) => {
1415 if self_pos == rhs_pos {
1416 commands.push(VecPatchCommand::Replace(rhs_pos, rhs_val));
1417 self_next = self_it.next();
1418 rhs_next = rhs_it.next();
1419 } else if self_pos < rhs_pos {
1420 commands.push(VecPatchCommand::Replace(self_pos, self_val));
1421 self_next = self_it.next();
1422 } else {
1423 commands.push(VecPatchCommand::Replace(rhs_pos, rhs_val));
1424 rhs_next = rhs_it.next();
1425 }
1426 }
1427 (
1428 VecPatchCommand::InsertBefore(self_pos, self_val),
1429 VecPatchCommand::InsertBefore(rhs_pos, mut rhs_val),
1430 )
1431 | (
1432 VecPatchCommand::InsertAfter(self_pos, self_val),
1433 VecPatchCommand::InsertAfter(rhs_pos, mut rhs_val),
1434 ) => {
1435 if self_pos == rhs_pos {
1436 rhs_val.extend(self_val);
1440 commands.push(rhs_command.clone());
1441 self_next = self_it.next();
1442 rhs_next = rhs_it.next();
1443 } else if self_pos < rhs_pos {
1444 commands.push(self_command.clone());
1445 self_next = self_it.next();
1446 } else {
1447 commands.push(rhs_command.clone());
1448 rhs_next = rhs_it.next();
1449 }
1450 }
1451 (
1452 VecPatchCommand::Replace(self_pos, _)
1453 | VecPatchCommand::InsertBefore(self_pos, _)
1454 | VecPatchCommand::InsertAfter(self_pos, _),
1455 VecPatchCommand::Replace(rhs_pos, _)
1456 | VecPatchCommand::InsertBefore(rhs_pos, _)
1457 | VecPatchCommand::InsertAfter(rhs_pos, _),
1458 ) => {
1459 if self_pos == rhs_pos {
1460 match (self_command, rhs_command) {
1461 (VecPatchCommand::InsertBefore(_, _), _)
1462 | (_, VecPatchCommand::InsertAfter(_, _)) => {
1463 commands.push(self_command.clone());
1464 self_next = self_it.next();
1465 }
1466 (_, VecPatchCommand::InsertBefore(_, _))
1467 | (VecPatchCommand::InsertAfter(_, _), _) => {
1468 commands.push(rhs_command.clone());
1469 rhs_next = rhs_it.next();
1470 }
1471 _ => panic!("This case should have been reached"),
1472 }
1473 } else if self_pos < rhs_pos {
1474 commands.push(self_command.clone());
1475 self_next = self_it.next();
1476 } else {
1477 commands.push(rhs_command.clone());
1478 rhs_next = rhs_it.next();
1479 }
1480 }
1481 }
1482 }
1483
1484 let remaining_commands = if self_next.is_some() {
1485 std::iter::once(self_next.unwrap()).chain(self_it)
1486 } else {
1487 std::iter::once(rhs_next.unwrap()).chain(self_it)
1488 };
1489 remaining_commands.for_each(|c| commands.push(c.clone()));
1490
1491 Self { commands }
1492 }
1493}
1494
1495impl<T, P> Merge for VecDeepPatch<T, P>
1496where
1497 T: Clone + Patch<P> + From<P>,
1498 P: Clone + Merge,
1499{
1500 fn merge(self, other: Self) -> Self {
1501 if other.commands.len() == 1
1502 && matches!(
1503 other.commands.first(),
1504 Some(VecDeepPatchCommand::ReplaceAll(_))
1505 )
1506 {
1507 return other;
1508 }
1509 if self.commands.len() == 1 {
1510 if let Some(VecDeepPatchCommand::ReplaceAll(self_vec)) = self.commands.first() {
1511 let mut self_vec = self_vec.clone();
1512 self_vec.apply(other);
1513 return VecDeepPatch {
1514 commands: vec![VecDeepPatchCommand::ReplaceAll(self_vec)],
1515 };
1516 }
1517 }
1518
1519 let mut commands: Vec<VecDeepPatchCommand<T, P>> = vec![];
1520
1521 let mut self_it = self.commands.iter();
1522 let mut rhs_it = other.commands.iter();
1523
1524 let mut self_next = self_it.next();
1525 let mut rhs_next = rhs_it.next();
1526
1527 while let (Some(self_command), Some(rhs_command)) = (self_next, rhs_next) {
1528 match (self_command.clone(), rhs_command.clone()) {
1529 (VecDeepPatchCommand::ReplaceAll(_), _)
1530 | (_, VecDeepPatchCommand::ReplaceAll(_)) => {
1531 panic!("Cannot combine a replace all with other commands");
1532 }
1533 (
1534 VecDeepPatchCommand::Append(elements),
1535 VecDeepPatchCommand::Append(rhs_elements),
1536 ) => {
1537 let mut elements = elements;
1540 elements.extend(rhs_elements);
1541 commands.push(VecDeepPatchCommand::Append(elements));
1542 self_next = self_it.next();
1543 rhs_next = rhs_it.next();
1544 }
1545 (self_command, VecDeepPatchCommand::Append(_)) => {
1546 commands.push(self_command);
1547 self_next = self_it.next();
1548 }
1549 (VecDeepPatchCommand::Append(_), rhs_command) => {
1550 commands.push(rhs_command);
1551 rhs_next = rhs_it.next();
1552 }
1553 (
1554 VecDeepPatchCommand::Replace(self_pos, self_val),
1555 VecDeepPatchCommand::Replace(rhs_pos, rhs_val),
1556 ) => {
1557 if self_pos == rhs_pos {
1558 commands.push(VecDeepPatchCommand::Replace(rhs_pos, rhs_val));
1559 self_next = self_it.next();
1560 rhs_next = rhs_it.next();
1561 } else if self_pos < rhs_pos {
1562 commands.push(VecDeepPatchCommand::Replace(self_pos, self_val));
1563 self_next = self_it.next();
1564 } else {
1565 commands.push(VecDeepPatchCommand::Replace(rhs_pos, rhs_val));
1566 rhs_next = rhs_it.next();
1567 }
1568 }
1569 (
1570 VecDeepPatchCommand::Replace(self_pos, self_val),
1571 VecDeepPatchCommand::Patch(rhs_pos, rhs_val),
1572 ) => {
1573 if self_pos == rhs_pos {
1574 let mut val = self_val.clone();
1575 val.apply(rhs_val);
1576 commands.push(VecDeepPatchCommand::Replace(rhs_pos, val));
1577 self_next = self_it.next();
1578 rhs_next = rhs_it.next();
1579 } else if self_pos < rhs_pos {
1580 commands.push(VecDeepPatchCommand::Replace(self_pos, self_val));
1581 self_next = self_it.next();
1582 } else {
1583 commands.push(VecDeepPatchCommand::Patch(rhs_pos, rhs_val));
1584 rhs_next = rhs_it.next();
1585 }
1586 }
1587 (
1588 VecDeepPatchCommand::Patch(self_pos, self_val),
1589 VecDeepPatchCommand::Replace(rhs_pos, rhs_val),
1590 ) => {
1591 if self_pos == rhs_pos {
1592 commands.push(VecDeepPatchCommand::Replace(rhs_pos, rhs_val));
1593 self_next = self_it.next();
1594 rhs_next = rhs_it.next();
1595 } else if self_pos < rhs_pos {
1596 commands.push(VecDeepPatchCommand::Patch(self_pos, self_val));
1597 self_next = self_it.next();
1598 } else {
1599 commands.push(VecDeepPatchCommand::Replace(rhs_pos, rhs_val));
1600 rhs_next = rhs_it.next();
1601 }
1602 }
1603 (
1604 VecDeepPatchCommand::Patch(self_pos, self_val),
1605 VecDeepPatchCommand::Patch(rhs_pos, rhs_val),
1606 ) => {
1607 if self_pos == rhs_pos {
1608 commands.push(VecDeepPatchCommand::Patch(rhs_pos, self_val.merge(rhs_val)));
1609 self_next = self_it.next();
1610 rhs_next = rhs_it.next();
1611 } else if self_pos < rhs_pos {
1612 commands.push(VecDeepPatchCommand::Patch(self_pos, self_val));
1613 self_next = self_it.next();
1614 } else {
1615 commands.push(VecDeepPatchCommand::Patch(rhs_pos, rhs_val));
1616 rhs_next = rhs_it.next();
1617 }
1618 }
1619 (
1620 VecDeepPatchCommand::InsertBefore(self_pos, self_val),
1621 VecDeepPatchCommand::InsertBefore(rhs_pos, mut rhs_val),
1622 )
1623 | (
1624 VecDeepPatchCommand::InsertAfter(self_pos, self_val),
1625 VecDeepPatchCommand::InsertAfter(rhs_pos, mut rhs_val),
1626 ) => {
1627 if self_pos == rhs_pos {
1628 rhs_val.extend(self_val);
1632 commands.push(rhs_command.clone());
1633 self_next = self_it.next();
1634 rhs_next = rhs_it.next();
1635 } else if self_pos < rhs_pos {
1636 commands.push(self_command.clone());
1637 self_next = self_it.next();
1638 } else {
1639 commands.push(rhs_command.clone());
1640 rhs_next = rhs_it.next();
1641 }
1642 }
1643 (
1644 VecDeepPatchCommand::Replace(_, _)
1645 | VecDeepPatchCommand::Patch(_, _)
1646 | VecDeepPatchCommand::InsertBefore(_, _)
1647 | VecDeepPatchCommand::InsertAfter(_, _),
1648 VecDeepPatchCommand::Replace(_, _)
1649 | VecDeepPatchCommand::Patch(_, _)
1650 | VecDeepPatchCommand::InsertBefore(_, _)
1651 | VecDeepPatchCommand::InsertAfter(_, _),
1652 ) => {
1653 if sort_commands(self_command, rhs_command) == Ordering::Less {
1654 commands.push(self_command.clone());
1655 self_next = self_it.next();
1656 } else {
1657 commands.push(rhs_command.clone());
1658 rhs_next = rhs_it.next();
1659 }
1660 }
1661 }
1662 }
1663
1664 let remaining_commands = if self_next.is_some() {
1665 std::iter::once(self_next.unwrap()).chain(self_it)
1666 } else {
1667 std::iter::once(rhs_next.unwrap()).chain(self_it)
1668 };
1669 remaining_commands.for_each(|c| commands.push(c.clone()));
1670
1671 Self { commands }
1672 }
1673}
1674
1675impl<K, V> Merge for HashMapPatch<K, V>
1676where
1677 K: Clone + Eq + Hash,
1678 V: Clone,
1679{
1680 fn merge(self, other: Self) -> Self {
1681 let mut patches = self.patches;
1682 for (key, value) in other.patches {
1683 match value {
1684 Some(value) => {
1685 patches.insert(key, Some(value));
1686 }
1687 None => {
1688 patches.remove(&key);
1689 }
1690 }
1691 }
1692 HashMapPatch { patches }
1693 }
1694}
1695
1696impl<K, V> Merge for HashMapDeepPatch<K, V>
1697where
1698 K: Clone + Eq + Hash,
1699 V: Clone + Merge,
1700{
1701 fn merge(mut self, other: Self) -> Self {
1702 for (key, value) in other.patches {
1703 match value {
1704 Some(value) => match self.patches.get_mut(&key) {
1705 Some(Some(patch)) => {
1706 *patch = patch.clone().merge(value);
1707 }
1708 _ => {
1709 self.patches.insert(key, Some(value));
1710 }
1711 },
1712 None => {
1713 self.patches.remove(&key);
1714 }
1715 }
1716 }
1717 self
1718 }
1719}
1720
1721#[cfg(not(feature = "strict"))]
1722impl<T> Merge for NestedMap<T>
1723where
1724 T: Clone,
1725{
1726 fn merge(mut self, other: Self) -> Self {
1727 let mut flatten = other.clone();
1728 flatten.flatten();
1729 self.flatten();
1730 for (key, value) in flatten.0 {
1731 self.0.insert(key.clone(), value.clone());
1732 }
1733 self
1734 }
1735}
1736
1737#[cfg(test)]
1740mod test {
1741 use super::*;
1742 use pretty_assertions_sorted::assert_eq_sorted;
1743
1744 #[cfg(feature = "permissive")]
1745 mod parsable_struct {
1746 use super::*;
1747
1748 #[test]
1749 fn deserialize_basic_user() {
1750 let user: ParsableStruct<UserPatch> = serde_yaml::from_str("user").unwrap();
1751
1752 assert_eq_sorted!(
1753 user,
1754 ParsableStruct(UserPatch {
1755 user: Some("user".into()),
1756 group: Some(None),
1757 })
1758 );
1759 }
1760
1761 #[test]
1762 fn deserialize_user_error_wrong_username() {
1763 let res = serde_yaml::from_str::<ParsableStruct<UserPatch>>("user*name");
1764
1765 assert!(res.is_err());
1766
1767 assert_eq_sorted!(
1768 res.unwrap_err().to_string(),
1769 "Error while parsing a permissive struct: Not matching chown pattern"
1770 );
1771 }
1772
1773 #[test]
1774 fn deserialize_stage_with_invalid_user() {
1775 let res = serde_yaml::from_str::<StagePatch>("user: user*name");
1776
1777 assert!(res.is_err());
1778
1779 assert_eq_sorted!(
1780 res.unwrap_err().to_string(),
1781 "user: Error while parsing a permissive struct: Not matching chown pattern at line 1 column 7"
1782 );
1783 }
1784
1785 #[ignore = "Not managed yet by serde because of multilevel flatten: https://serde.rs/field-attrs.html#flatten"]
1786 #[test]
1787 fn deserialize_dofigen_with_invalid_user() {
1788 let res = serde_yaml::from_str::<DofigenPatch>("user: user*name");
1789
1790 assert!(res.is_err());
1791
1792 assert_eq_sorted!(
1793 res.unwrap_err().to_string(),
1794 "user: Error while parsing a permissive struct: Not matching chown pattern at line 1 column 7"
1795 );
1796 }
1797 }
1798
1799 mod vec_patch {
1800 use super::*;
1801 use serde::Deserialize;
1802 use struct_patch::Patch;
1803
1804 #[derive(Debug, Clone, PartialEq, Patch, Default)]
1805 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
1806 struct TestStruct {
1807 pub name: String,
1808 #[patch(name = "Option<SubTestStructPatch>")]
1809 pub sub: Option<SubTestStruct>,
1810 }
1811
1812 #[derive(Debug, Clone, PartialEq, Patch, Default)]
1813 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
1814 struct SubTestStruct {
1815 #[patch(name = "VecPatch<String>")]
1816 pub list: Vec<String>,
1817 pub num: Option<u32>,
1818 }
1819
1820 impl From<TestStructPatch> for TestStruct {
1821 fn from(patch: TestStructPatch) -> Self {
1822 let mut sub = Self::default();
1823 sub.apply(patch);
1824 sub
1825 }
1826 }
1827
1828 impl From<SubTestStructPatch> for SubTestStruct {
1829 fn from(patch: SubTestStructPatch) -> Self {
1830 let mut sub = Self::default();
1831 sub.apply(patch);
1832 sub
1833 }
1834 }
1835
1836 #[test]
1837 fn test_simple_patch() {
1838 let base = r#"
1839 name: patch1
1840 sub:
1841 list:
1842 - item1
1843 - item2
1844 num: 42
1845 "#;
1846
1847 let patch = r#"
1848 name: patch2
1849 sub:
1850 num: 43
1851 "#;
1852
1853 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
1854 .unwrap()
1855 .into();
1856 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
1857
1858 base_data.apply(patch_data);
1859
1860 assert_eq_sorted!(
1861 base_data,
1862 TestStruct {
1863 name: "patch2".into(),
1864 sub: Some(SubTestStruct {
1865 list: vec!["item1".into(), "item2".into()],
1866 num: Some(43)
1867 })
1868 }
1869 );
1870 }
1871
1872 #[test]
1873 fn test_vec_replace() {
1874 let base = r#"
1875 name: patch1
1876 sub:
1877 list:
1878 - item1
1879 - item2
1880 num: 42
1881 "#;
1882
1883 let patch = r#"
1884 sub:
1885 list:
1886 - item3
1887 - item4
1888 "#;
1889
1890 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
1891 .unwrap()
1892 .into();
1893 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
1894
1895 base_data.apply(patch_data);
1896
1897 assert_eq_sorted!(
1898 base_data,
1899 TestStruct {
1900 name: "patch1".into(),
1901 sub: Some(SubTestStruct {
1902 list: vec!["item3".into(), "item4".into()],
1903 num: Some(42)
1904 })
1905 }
1906 );
1907 }
1908
1909 #[test]
1910 fn test_vec_append_list_patch() {
1911 let base = r#"
1912 name: patch1
1913 sub:
1914 list:
1915 - item1
1916 - item2
1917 num: 42
1918 "#;
1919
1920 let patch = r#"
1921 sub:
1922 list:
1923 +:
1924 - item3
1925 - item4
1926 "#;
1927
1928 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
1929 .unwrap()
1930 .into();
1931 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
1932
1933 base_data.apply(patch_data);
1934
1935 assert_eq_sorted!(
1936 base_data,
1937 TestStruct {
1938 name: "patch1".into(),
1939 sub: Some(SubTestStruct {
1940 list: vec![
1941 "item1".into(),
1942 "item2".into(),
1943 "item3".into(),
1944 "item4".into()
1945 ],
1946 num: Some(42)
1947 })
1948 }
1949 );
1950 }
1951
1952 #[cfg(feature = "permissive")]
1953 #[test]
1954 fn test_vec_append_one_patch() {
1955 let base = r#"
1956 name: patch1
1957 sub:
1958 list:
1959 - item1
1960 - item2
1961 num: 42
1962 "#;
1963
1964 let patch = r#"
1965 sub:
1966 list:
1967 +: item3
1968 "#;
1969
1970 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
1971 .unwrap()
1972 .into();
1973 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
1974
1975 base_data.apply(patch_data);
1976
1977 assert_eq_sorted!(
1978 base_data,
1979 TestStruct {
1980 name: "patch1".into(),
1981 sub: Some(SubTestStruct {
1982 list: vec!["item1".into(), "item2".into(), "item3".into()],
1983 num: Some(42)
1984 })
1985 }
1986 );
1987 }
1988
1989 #[test]
1990 fn test_vec_replace_patch() {
1991 let base = r#"
1992 name: patch1
1993 sub:
1994 list:
1995 - item1
1996 - item2
1997 - item3
1998 - item4
1999 num: 42
2000 "#;
2001
2002 let patch = r#"
2003 sub:
2004 list:
2005 1: item5
2006 3: item6
2007 "#;
2008
2009 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2010 .unwrap()
2011 .into();
2012 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2013
2014 base_data.apply(patch_data);
2015
2016 assert_eq_sorted!(
2017 base_data,
2018 TestStruct {
2019 name: "patch1".into(),
2020 sub: Some(SubTestStruct {
2021 list: vec![
2022 "item1".into(),
2023 "item5".into(),
2024 "item3".into(),
2025 "item6".into()
2026 ],
2027 num: Some(42)
2028 })
2029 }
2030 );
2031 }
2032
2033 #[test]
2034 fn test_vec_insert_before_patch() {
2035 let base = r#"
2036 name: patch1
2037 sub:
2038 list:
2039 - item1
2040 - item2
2041 - item3
2042 - item4
2043 num: 42
2044 "#;
2045
2046 let patch = r#"
2047 sub:
2048 list:
2049 "+1":
2050 - item5
2051 - item6
2052 "#;
2053
2054 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2055 .unwrap()
2056 .into();
2057 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2058
2059 base_data.apply(patch_data);
2060
2061 assert_eq_sorted!(
2062 base_data,
2063 TestStruct {
2064 name: "patch1".into(),
2065 sub: Some(SubTestStruct {
2066 list: vec![
2067 "item1".into(),
2068 "item5".into(),
2069 "item6".into(),
2070 "item2".into(),
2071 "item3".into(),
2072 "item4".into()
2073 ],
2074 num: Some(42)
2075 })
2076 }
2077 );
2078 }
2079
2080 #[test]
2081 fn test_vec_insert_after_patch() {
2082 let base = r#"
2083 name: patch1
2084 sub:
2085 list:
2086 - item1
2087 - item2
2088 - item3
2089 - item4
2090 num: 42
2091 "#;
2092
2093 let patch = r#"
2094 sub:
2095 list:
2096 1+:
2097 - item5
2098 - item6
2099 "#;
2100
2101 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2102 .unwrap()
2103 .into();
2104 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2105
2106 base_data.apply(patch_data);
2107
2108 assert_eq_sorted!(
2109 base_data,
2110 TestStruct {
2111 name: "patch1".into(),
2112 sub: Some(SubTestStruct {
2113 list: vec![
2114 "item1".into(),
2115 "item2".into(),
2116 "item5".into(),
2117 "item6".into(),
2118 "item3".into(),
2119 "item4".into()
2120 ],
2121 num: Some(42)
2122 })
2123 }
2124 );
2125 }
2126
2127 #[test]
2128 fn test_vec_many_operations_patch() {
2129 let base = r#"
2130 name: patch1
2131 sub:
2132 list:
2133 - item1
2134 - item2
2135 - item3
2136 - item4
2137 num: 42
2138 "#;
2139
2140 let patch = r#"
2141 sub:
2142 list:
2143 "+2":
2144 - item6
2145 1+:
2146 - item5
2147 +:
2148 - item7
2149 0: item0
2150 "#;
2151
2152 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2153 .unwrap()
2154 .into();
2155 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2156
2157 base_data.apply(patch_data);
2158
2159 assert_eq_sorted!(
2160 base_data,
2161 TestStruct {
2162 name: "patch1".into(),
2163 sub: Some(SubTestStruct {
2164 list: vec![
2165 "item0".into(),
2166 "item2".into(),
2167 "item5".into(),
2168 "item6".into(),
2169 "item3".into(),
2170 "item4".into(),
2171 "item7".into()
2172 ],
2173 num: Some(42)
2174 })
2175 }
2176 );
2177 }
2178 }
2179
2180 mod vec_deep_patch {
2181 use super::*;
2182 use serde::Deserialize;
2183 use struct_patch::Patch;
2184
2185 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2186 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2187 struct TestStruct {
2188 pub name: String,
2189 #[patch(name = "VecDeepPatch<SubTestStruct, SubTestStructPatch>")]
2190 pub subs: Vec<SubTestStruct>,
2191 }
2192
2193 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2194 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2195 struct SubTestStruct {
2196 pub name: String,
2197 pub num: u32,
2198 }
2199
2200 impl From<TestStructPatch> for TestStruct {
2201 fn from(patch: TestStructPatch) -> Self {
2202 let mut sub = Self::default();
2203 sub.apply(patch);
2204 sub
2205 }
2206 }
2207
2208 impl From<SubTestStructPatch> for SubTestStruct {
2209 fn from(patch: SubTestStructPatch) -> Self {
2210 let mut sub = Self::default();
2211 sub.apply(patch);
2212 sub
2213 }
2214 }
2215
2216 #[test]
2217 fn test_simple_patch() {
2218 let base = r#"
2219 name: patch1
2220 subs:
2221 - name: sub1
2222 num: 1
2223 - name: sub2
2224 num: 2
2225 "#;
2226
2227 let patch = r#"
2228 name: patch2
2229 "#;
2230
2231 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2232 .unwrap()
2233 .into();
2234 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2235
2236 base_data.apply(patch_data);
2237
2238 assert_eq_sorted!(
2239 base_data,
2240 TestStruct {
2241 name: "patch2".into(),
2242 subs: vec![
2243 SubTestStruct {
2244 name: "sub1".into(),
2245 num: 1
2246 },
2247 SubTestStruct {
2248 name: "sub2".into(),
2249 num: 2
2250 }
2251 ],
2252 }
2253 );
2254 }
2255
2256 #[test]
2257 fn test_vec_replace() {
2258 let base = r#"
2259 name: patch1
2260 subs:
2261 - name: sub1
2262 num: 1
2263 - name: sub2
2264 num: 2
2265 "#;
2266
2267 let patch = r#"
2268 subs:
2269 - name: sub3
2270 num: 3
2271 - name: sub4
2272 num: 4
2273 "#;
2274
2275 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2276 .unwrap()
2277 .into();
2278 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2279
2280 base_data.apply(patch_data);
2281
2282 assert_eq_sorted!(
2283 base_data,
2284 TestStruct {
2285 name: "patch1".into(),
2286 subs: vec![
2287 SubTestStruct {
2288 name: "sub3".into(),
2289 num: 3
2290 },
2291 SubTestStruct {
2292 name: "sub4".into(),
2293 num: 4
2294 }
2295 ]
2296 }
2297 );
2298 }
2299
2300 #[test]
2301 fn test_vec_append_list_patch() {
2302 let base = r#"
2303 name: patch1
2304 subs:
2305 - name: sub1
2306 num: 1
2307 - name: sub2
2308 num: 2
2309 "#;
2310
2311 let patch = r#"
2312 subs:
2313 +:
2314 - name: sub3
2315 num: 3
2316 - name: sub4
2317 num: 4
2318 "#;
2319
2320 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2321 .unwrap()
2322 .into();
2323 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2324
2325 base_data.apply(patch_data);
2326
2327 assert_eq_sorted!(
2328 base_data,
2329 TestStruct {
2330 name: "patch1".into(),
2331 subs: vec![
2332 SubTestStruct {
2333 name: "sub1".into(),
2334 num: 1
2335 },
2336 SubTestStruct {
2337 name: "sub2".into(),
2338 num: 2
2339 },
2340 SubTestStruct {
2341 name: "sub3".into(),
2342 num: 3
2343 },
2344 SubTestStruct {
2345 name: "sub4".into(),
2346 num: 4
2347 }
2348 ]
2349 }
2350 );
2351 }
2352
2353 #[cfg(feature = "permissive")]
2354 #[test]
2355 fn test_vec_append_one_patch() {
2356 let base = r#"
2357 name: patch1
2358 subs:
2359 - name: sub1
2360 num: 1
2361 - name: sub2
2362 num: 2
2363 "#;
2364
2365 let patch = r#"
2366 subs:
2367 +:
2368 name: sub3
2369 num: 3
2370 "#;
2371
2372 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2373 .unwrap()
2374 .into();
2375 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2376
2377 base_data.apply(patch_data);
2378
2379 assert_eq_sorted!(
2380 base_data,
2381 TestStruct {
2382 name: "patch1".into(),
2383 subs: vec![
2384 SubTestStruct {
2385 name: "sub1".into(),
2386 num: 1
2387 },
2388 SubTestStruct {
2389 name: "sub2".into(),
2390 num: 2
2391 },
2392 SubTestStruct {
2393 name: "sub3".into(),
2394 num: 3
2395 }
2396 ]
2397 }
2398 );
2399 }
2400
2401 #[test]
2402 fn test_vec_replace_patch() {
2403 let base = r#"
2404 name: patch1
2405 subs:
2406 - name: sub1
2407 num: 1
2408 - name: sub2
2409 num: 2
2410 "#;
2411
2412 let patch = r#"
2413 subs:
2414 1:
2415 name: sub3
2416 num: 3
2417 "#;
2418
2419 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2420 .unwrap()
2421 .into();
2422 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2423
2424 base_data.apply(patch_data);
2425
2426 assert_eq_sorted!(
2427 base_data,
2428 TestStruct {
2429 name: "patch1".into(),
2430 subs: vec![
2431 SubTestStruct {
2432 name: "sub1".into(),
2433 num: 1
2434 },
2435 SubTestStruct {
2436 name: "sub3".into(),
2437 num: 3
2438 },
2439 ]
2440 }
2441 );
2442 }
2443
2444 #[test]
2445 fn test_vec_deep_patch() {
2446 let base = r#"
2447 name: patch1
2448 subs:
2449 - name: sub1
2450 num: 1
2451 - name: sub2
2452 num: 2
2453 "#;
2454
2455 let patch = r#"
2456 subs:
2457 0<:
2458 num: 3
2459 "#;
2460
2461 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2462 .unwrap()
2463 .into();
2464 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2465
2466 base_data.apply(patch_data);
2467
2468 assert_eq_sorted!(
2469 base_data,
2470 TestStruct {
2471 name: "patch1".into(),
2472 subs: vec![
2473 SubTestStruct {
2474 name: "sub1".into(),
2475 num: 3
2476 },
2477 SubTestStruct {
2478 name: "sub2".into(),
2479 num: 2
2480 },
2481 ]
2482 }
2483 );
2484 }
2485
2486 #[test]
2487 fn test_vec_insert_before_patch() {
2488 let base = r#"
2489 name: patch1
2490 subs:
2491 - name: sub1
2492 num: 1
2493 - name: sub2
2494 num: 2
2495 - name: sub3
2496 num: 3
2497 - name: sub4
2498 num: 4
2499 "#;
2500
2501 let patch = r#"
2502 subs:
2503 "+1":
2504 - name: sub5
2505 num: 5
2506 - name: sub6
2507 num: 6
2508 "#;
2509
2510 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2511 .unwrap()
2512 .into();
2513 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2514
2515 base_data.apply(patch_data);
2516
2517 assert_eq_sorted!(
2518 base_data,
2519 TestStruct {
2520 name: "patch1".into(),
2521 subs: vec![
2522 SubTestStruct {
2523 name: "sub1".into(),
2524 num: 1
2525 },
2526 SubTestStruct {
2527 name: "sub5".into(),
2528 num: 5
2529 },
2530 SubTestStruct {
2531 name: "sub6".into(),
2532 num: 6
2533 },
2534 SubTestStruct {
2535 name: "sub2".into(),
2536 num: 2
2537 },
2538 SubTestStruct {
2539 name: "sub3".into(),
2540 num: 3
2541 },
2542 SubTestStruct {
2543 name: "sub4".into(),
2544 num: 4
2545 },
2546 ]
2547 }
2548 );
2549 }
2550
2551 #[test]
2552 fn test_vec_insert_after_patch() {
2553 let base = r#"
2554 name: patch1
2555 subs:
2556 - name: sub1
2557 num: 1
2558 - name: sub2
2559 num: 2
2560 - name: sub3
2561 num: 3
2562 - name: sub4
2563 num: 4
2564 "#;
2565
2566 let patch = r#"
2567 subs:
2568 1+:
2569 - name: sub5
2570 num: 5
2571 - name: sub6
2572 num: 6
2573 "#;
2574
2575 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2576 .unwrap()
2577 .into();
2578 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2579
2580 base_data.apply(patch_data);
2581
2582 assert_eq_sorted!(
2583 base_data,
2584 TestStruct {
2585 name: "patch1".into(),
2586 subs: vec![
2587 SubTestStruct {
2588 name: "sub1".into(),
2589 num: 1
2590 },
2591 SubTestStruct {
2592 name: "sub2".into(),
2593 num: 2
2594 },
2595 SubTestStruct {
2596 name: "sub5".into(),
2597 num: 5
2598 },
2599 SubTestStruct {
2600 name: "sub6".into(),
2601 num: 6
2602 },
2603 SubTestStruct {
2604 name: "sub3".into(),
2605 num: 3
2606 },
2607 SubTestStruct {
2608 name: "sub4".into(),
2609 num: 4
2610 },
2611 ]
2612 }
2613 );
2614 }
2615
2616 #[test]
2617 fn test_vec_many_operations_patch() {
2618 let base = r#"
2619 name: patch1
2620 subs:
2621 - name: sub1
2622 num: 1
2623 - name: sub2
2624 num: 2
2625 - name: sub3
2626 num: 3
2627 - name: sub4
2628 num: 4
2629 "#;
2630
2631 let patch = r#"
2632 subs:
2633 "+2":
2634 - name: sub6
2635 num: 6
2636 1+:
2637 - name: sub5
2638 num: 5
2639 +:
2640 - name: sub7
2641 num: 7
2642 0:
2643 name: sub0
2644 num: 0
2645 1<:
2646 num: 1
2647 "#;
2648
2649 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2650 .unwrap()
2651 .into();
2652 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2653
2654 base_data.apply(patch_data);
2655
2656 assert_eq_sorted!(
2657 base_data,
2658 TestStruct {
2659 name: "patch1".into(),
2660 subs: vec![
2661 SubTestStruct {
2662 name: "sub0".into(),
2663 num: 0
2664 },
2665 SubTestStruct {
2666 name: "sub2".into(),
2667 num: 1
2668 },
2669 SubTestStruct {
2670 name: "sub5".into(),
2671 num: 5
2672 },
2673 SubTestStruct {
2674 name: "sub6".into(),
2675 num: 6
2676 },
2677 SubTestStruct {
2678 name: "sub3".into(),
2679 num: 3
2680 },
2681 SubTestStruct {
2682 name: "sub4".into(),
2683 num: 4
2684 },
2685 SubTestStruct {
2686 name: "sub7".into(),
2687 num: 7
2688 },
2689 ]
2690 }
2691 );
2692 }
2693 }
2694
2695 mod hashmap_patch {
2696 use super::*;
2697 use serde::Deserialize;
2698 use struct_patch::Patch;
2699
2700 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2701 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2702 struct TestStruct {
2703 pub name: String,
2704 #[patch(name = "HashMapPatch<String, String>")]
2705 pub subs: HashMap<String, String>,
2706 }
2707
2708 impl From<TestStructPatch> for TestStruct {
2709 fn from(patch: TestStructPatch) -> Self {
2710 let mut sub = Self::default();
2711 sub.apply(patch);
2712 sub
2713 }
2714 }
2715
2716 #[test]
2717 fn test_simple_patch() {
2718 let base = r#"
2719 name: patch1
2720 subs:
2721 sub1: value1
2722 sub2: value2
2723 "#;
2724
2725 let patch = r#"
2726 name: patch2
2727 subs:
2728 sub2: null
2729 sub3: value3
2730 "#;
2731
2732 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2733 .unwrap()
2734 .into();
2735 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2736
2737 base_data.apply(patch_data);
2738
2739 assert_eq_sorted!(
2740 base_data,
2741 TestStruct {
2742 name: "patch2".into(),
2743 subs: HashMap::from([
2744 ("sub1".to_string(), "value1".to_string()),
2745 ("sub3".to_string(), "value3".to_string())
2746 ])
2747 }
2748 );
2749 }
2750 }
2751
2752 mod hashmap_deep_patch {
2753 use super::*;
2754 use serde::Deserialize;
2755 use struct_patch::Patch;
2756
2757 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2758 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2759 struct TestStruct {
2760 pub name: String,
2761 #[patch(name = "HashMapDeepPatch<String, TestSubStructPatch>")]
2762 pub subs: HashMap<String, TestSubStruct>,
2763 }
2764
2765 #[derive(Debug, Clone, PartialEq, Patch, Default)]
2766 #[patch(attribute(derive(Deserialize, Debug, Clone, PartialEq, Default)))]
2767 struct TestSubStruct {
2768 pub name: String,
2769 }
2770
2771 impl From<TestStructPatch> for TestStruct {
2772 fn from(patch: TestStructPatch) -> Self {
2773 let mut sub = Self::default();
2774 sub.apply(patch);
2775 sub
2776 }
2777 }
2778
2779 impl From<TestSubStructPatch> for TestSubStruct {
2780 fn from(patch: TestSubStructPatch) -> Self {
2781 let mut sub = Self::default();
2782 sub.apply(patch);
2783 sub
2784 }
2785 }
2786
2787 #[test]
2788 fn test_simple_patch() {
2789 let base = r#"
2790 name: patch1
2791 subs:
2792 sub1:
2793 name: value1
2794 sub2:
2795 name: value2
2796 "#;
2797
2798 let patch = r#"
2799 name: patch2
2800 subs:
2801 sub1:
2802 name: value2
2803 sub2: null
2804 sub3:
2805 name: value3
2806 "#;
2807
2808 let mut base_data: TestStruct = serde_yaml::from_str::<TestStructPatch>(base)
2809 .unwrap()
2810 .into();
2811 let patch_data: TestStructPatch = serde_yaml::from_str(patch).unwrap();
2812
2813 base_data.apply(patch_data);
2814
2815 assert_eq_sorted!(
2816 base_data,
2817 TestStruct {
2818 name: "patch2".into(),
2819 subs: HashMap::from([
2820 (
2821 "sub1".to_string(),
2822 TestSubStruct {
2823 name: "value2".to_string()
2824 }
2825 ),
2826 (
2827 "sub3".to_string(),
2828 TestSubStruct {
2829 name: "value3".to_string()
2830 }
2831 )
2832 ])
2833 }
2834 );
2835 }
2836 }
2837
2838 #[cfg(feature = "permissive")]
2839 mod nested_map {
2840
2841 use super::*;
2842
2843 #[test]
2844 fn test_nested_map_patch() {
2845 let mut base_data: HashMap<String, String> =
2846 HashMap::from([("key1.key2".to_string(), "value2".to_string())]);
2847 let patch_data: NestedMap<String> = NestedMap(HashMap::from([
2848 (
2849 "key1".to_string(),
2850 NestedMapValue::Map(NestedMap(HashMap::from([(
2851 "key2".to_string(),
2852 NestedMapValue::Value("patch 1".to_string()),
2853 )]))),
2854 ),
2855 (
2856 "key1.key3".to_string(),
2857 NestedMapValue::Value("value3".to_string()),
2858 ),
2859 ]));
2860
2861 base_data.apply(patch_data);
2862
2863 assert_eq!(
2864 base_data,
2865 HashMap::from([
2866 ("key1.key2".to_string(), "patch 1".to_string()),
2867 ("key1.key3".to_string(), "value3".to_string())
2868 ])
2869 );
2870 }
2871 }
2872
2873 #[cfg(feature = "permissive")]
2874 mod deserialize {
2875 use super::*;
2876
2877 mod one_or_many {
2878 use super::*;
2879
2880 #[derive(Deserialize, Debug, Clone, PartialEq)]
2881 struct TestStruct {
2882 pub one_or_many: OneOrMany<String>,
2883 }
2884
2885 #[test]
2886 fn one() {
2887 let ret: TestStruct = serde_yaml::from_str("one_or_many: test").unwrap();
2888 assert_eq_sorted!(
2889 ret,
2890 TestStruct {
2891 one_or_many: OneOrMany(vec!["test".into()])
2892 }
2893 )
2894 }
2895
2896 #[test]
2897 fn many() {
2898 let ret: TestStruct = serde_yaml::from_str("one_or_many: [test]").unwrap();
2899 assert_eq_sorted!(
2900 ret,
2901 TestStruct {
2902 one_or_many: OneOrMany(vec!["test".into()])
2903 }
2904 )
2905 }
2906 }
2907
2908 mod optional_one_or_many {
2909 use super::*;
2910
2911 #[derive(Deserialize, Debug, Clone, PartialEq, Default)]
2912 struct TestStruct {
2913 pub test: Option<String>,
2914 pub one_or_many: Option<OneOrMany<String>>,
2915 }
2916
2917 #[test]
2918 fn one() {
2919 let ret: TestStruct = serde_yaml::from_str("one_or_many: test").unwrap();
2920 assert_eq_sorted!(
2921 ret,
2922 TestStruct {
2923 test: None,
2924 one_or_many: Some(OneOrMany(vec!["test".into()]))
2925 }
2926 )
2927 }
2928
2929 #[test]
2930 fn many() {
2931 let ret: TestStruct = serde_yaml::from_str("one_or_many: [test]").unwrap();
2932 assert_eq_sorted!(
2933 ret,
2934 TestStruct {
2935 test: None,
2936 one_or_many: Some(OneOrMany(vec!["test".into()]))
2937 }
2938 )
2939 }
2940
2941 #[test]
2942 fn null() {
2943 let ret: TestStruct = serde_yaml::from_str("one_or_many: null").unwrap();
2944 assert_eq_sorted!(
2945 ret,
2946 TestStruct {
2947 test: None,
2948 one_or_many: None
2949 }
2950 )
2951 }
2952
2953 #[test]
2954 fn absent() {
2955 let ret: TestStruct = serde_yaml::from_str("test: test").unwrap();
2956 assert_eq_sorted!(
2957 ret,
2958 TestStruct {
2959 test: Some("test".into()),
2960 one_or_many: None
2961 }
2962 )
2963 }
2964 }
2965
2966 #[cfg(feature = "permissive")]
2967 mod from_optional_string_or_number {
2968 use super::*;
2969
2970 #[derive(Deserialize, Debug, Clone, PartialEq, Default)]
2971 struct TestStruct {
2972 #[serde(
2973 deserialize_with = "deserialize_from_optional_string_or_number",
2974 default
2975 )]
2976 pub test: Option<Option<String>>,
2977 }
2978
2979 #[test]
2980 fn string() {
2981 let ret: TestStruct = serde_yaml::from_str("test: \"123\"").unwrap();
2982 assert_eq_sorted!(
2983 ret,
2984 TestStruct {
2985 test: Some(Some("123".into()))
2986 }
2987 )
2988 }
2989
2990 #[test]
2991 fn number() {
2992 let ret: TestStruct = serde_yaml::from_str("test: 123").unwrap();
2993 assert_eq_sorted!(
2994 ret,
2995 TestStruct {
2996 test: Some(Some("123".into()))
2997 }
2998 )
2999 }
3000
3001 #[test]
3002 fn null() {
3003 let ret: TestStruct = serde_yaml::from_str("test: null").unwrap();
3004 assert_eq_sorted!(ret, TestStruct { test: Some(None) })
3005 }
3006
3007 #[test]
3008 fn absent() {
3009 let ret: TestStruct = serde_yaml::from_str("").unwrap();
3010 assert_eq_sorted!(ret, TestStruct { test: None })
3011 }
3012 }
3013
3014 mod nested_map {
3015
3016 use super::*;
3017
3018 #[test]
3019 fn test_single_level_map() {
3020 let yaml = r#"
3021 key1: value1
3022 key2: value2
3023 key3:
3024 "#;
3025
3026 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3027
3028 assert_eq!(
3029 result,
3030 NestedMap(HashMap::from([
3031 (
3032 "key1".to_string(),
3033 NestedMapValue::Value("value1".to_string())
3034 ),
3035 (
3036 "key2".to_string(),
3037 NestedMapValue::Value("value2".to_string())
3038 ),
3039 ("key3".to_string(), NestedMapValue::Null)
3040 ]))
3041 );
3042 }
3043
3044 #[test]
3045 fn test_multilevel_map() {
3046 let yaml = r#"
3047 key1:
3048 key2: value
3049 "#;
3050
3051 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3052
3053 assert_eq!(
3054 result,
3055 NestedMap(HashMap::from([(
3056 "key1".to_string(),
3057 NestedMapValue::Map(NestedMap(HashMap::from([(
3058 "key2".to_string(),
3059 NestedMapValue::Value("value".to_string())
3060 )])))
3061 )]))
3062 );
3063 }
3064
3065 #[test]
3066 fn test_equivalent_flattened_map() {
3067 let yaml = r#"
3068 key1.key2: value
3069 "#;
3070
3071 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3072
3073 assert_eq!(
3074 result,
3075 NestedMap(HashMap::from([(
3076 "key1.key2".to_string(),
3077 NestedMapValue::Value("value".to_string())
3078 )]))
3079 );
3080 }
3081
3082 #[test]
3083 fn test_combined_multilevel_and_flattened_map() {
3084 let yaml = r#"
3085 key1:
3086 key2: value2
3087 key1.key3: value3
3088 "#;
3089
3090 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3091
3092 assert_eq!(
3093 result,
3094 NestedMap(HashMap::from([
3095 (
3096 "key1".to_string(),
3097 NestedMapValue::Map(NestedMap(HashMap::from([(
3098 "key2".to_string(),
3099 NestedMapValue::Value("value2".to_string())
3100 )])))
3101 ),
3102 (
3103 "key1.key3".to_string(),
3104 NestedMapValue::Value("value3".to_string())
3105 )
3106 ]))
3107 );
3108 }
3109
3110 #[test]
3111 fn test_empty_map() {
3112 let yaml = r#"
3113 "#;
3114
3115 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3116
3117 assert_eq!(result, NestedMap(HashMap::new()));
3118 }
3119
3120 #[test]
3121 fn test_nested_empty_map() {
3122 let yaml = r#"
3123 key1: {}
3124 "#;
3125
3126 let result: NestedMap<String> = serde_yaml::from_str(yaml).unwrap();
3127
3128 assert_eq!(
3129 result,
3130 NestedMap(HashMap::from([(
3131 "key1".to_string(),
3132 NestedMapValue::Map(NestedMap(HashMap::new()))
3133 )]))
3134 );
3135 }
3136 }
3137 }
3138}