attribute_derive/
from_partial.rs

1//! Contains utilities for implementing [`FromPartial`].
2use crate::*;
3
4/// Converts from a [`Partial`](AttributeBase::Partial) value.
5pub trait FromPartial<T>: Sized {
6    /// Creates `Self` from `T`.
7    ///
8    /// # Errors
9    /// Returns a [`syn::Error`] when `T` does not represent a valid `Self`,
10    /// e.g., due to missing or conflicting fields.
11    fn from(partial: T) -> Result<Self>;
12
13    /// Creates `Self` from optional `T`.
14    ///
15    /// # Errors
16    /// The default implementation errors with `error_missing` when `partial` is
17    /// [`None`], or when `Self::from` errors.
18    ///
19    /// Implementors might override this for types with expected default values.
20    fn from_option(partial: Option<T>, error_missing: &str) -> Result<Self> {
21        // Pass in surrounding span
22        partial
23            .map(Self::from)
24            .transpose()?
25            .ok_or_else(|| syn::Error::new(Span::call_site(), error_missing))
26    }
27
28    /// Defines how two arguments for the same parameter should be handled.
29    ///
30    /// # Errors
31    /// The default implementation errors if `first` is already present and
32    /// `specified_twice_error` is returned with the correct spans.
33    fn join(
34        first: Option<SpannedValue<T>>,
35        second: SpannedValue<T>,
36        specified_twice_error: &str,
37    ) -> Result<Option<SpannedValue<T>>> {
38        if let Some(first) = first {
39            if let Some(span) = first
40                .span()
41                .span_joined()
42                .and_then(|s| Some((s, second.span().span_joined()?)))
43                .and_then(|(a, b)| a.join(b))
44            {
45                Err(Error::new(span, specified_twice_error))
46            } else {
47                let mut error = Error::new(first.span().start, specified_twice_error);
48                error.combine(Error::new(second.span().start, specified_twice_error));
49                Err(error)
50            }
51        } else {
52            Ok(Some(second))
53        }
54    }
55}
56
57impl<T> FromPartial<T> for T {
58    fn from(partial: T) -> Result<Self> {
59        Ok(partial)
60    }
61}
62
63/// [`FromPartial`] wrapper that uses [`Default`] value when not specified.
64#[derive(Clone)]
65pub struct Defaulting<T>(pub T);
66
67impl<P, T: Default + FromPartial<P>> FromPartial<Defaulting<P>> for T {
68    fn from(partial: Defaulting<P>) -> Result<Self> {
69        Self::from(partial.0)
70    }
71
72    fn from_option(partial: Option<Defaulting<P>>, _error: &str) -> Result<Self> {
73        partial
74            .map(|d| Self::from(d.0))
75            .transpose()
76            .map(Option::unwrap_or_default)
77    }
78}
79
80/// Utility struct to avoid duplicate trait definition when using `Self<A>` for
81/// `<Self<B> as BaseAttribute>::Partial`.
82pub struct Partial<T>(pub T);