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