dofigen_lib/
deserialize.rs

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