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