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