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