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