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