Skip to main content

dofigen_lib/
deserialize.rs

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