darling_core/util/
spanned_value.rs1use proc_macro2::Span;
2use std::ops::{Deref, DerefMut};
3use syn::spanned::Spanned;
4
5use crate::{
6 FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, FromTypeParam,
7 FromVariant, Result,
8};
9
10#[derive(Debug, Clone, Copy)]
23pub struct SpannedValue<T> {
24 value: T,
25 span: Span,
26}
27
28impl<T> SpannedValue<T> {
29 pub fn new(value: T, span: Span) -> Self {
30 SpannedValue { value, span }
31 }
32
33 pub fn span(&self) -> Span {
35 self.span
36 }
37
38 pub fn map_ref<U>(&self, map_fn: impl FnOnce(&T) -> U) -> SpannedValue<U> {
40 SpannedValue::new(map_fn(&self.value), self.span)
41 }
42
43 pub fn into_inner(self) -> T {
45 self.value
46 }
47}
48
49impl<T: Default> Default for SpannedValue<T> {
50 fn default() -> Self {
51 SpannedValue::new(Default::default(), Span::call_site())
52 }
53}
54
55impl<T> Deref for SpannedValue<T> {
56 type Target = T;
57
58 fn deref(&self) -> &T {
59 &self.value
60 }
61}
62
63impl<T> DerefMut for SpannedValue<T> {
64 fn deref_mut(&mut self) -> &mut T {
65 &mut self.value
66 }
67}
68
69impl<T> AsRef<T> for SpannedValue<T> {
70 fn as_ref(&self) -> &T {
71 &self.value
72 }
73}
74
75macro_rules! spanned {
76 ($trayt:ident, $method:ident, $syn:path) => {
77 impl<T: $trayt> $trayt for SpannedValue<T> {
78 fn $method(value: &$syn) -> Result<Self> {
79 Ok(SpannedValue::new(
80 $trayt::$method(value).map_err(|e| e.with_span(value))?,
81 value.span(),
82 ))
83 }
84 }
85 };
86}
87
88impl<T: FromMeta> FromMeta for SpannedValue<T> {
89 fn from_meta(item: &syn::Meta) -> Result<Self> {
90 let value = T::from_meta(item).map_err(|e| e.with_span(item))?;
91 let span = match item {
92 syn::Meta::Path(path) => path.span(),
95 syn::Meta::List(list) => list.tokens.span(),
98 syn::Meta::NameValue(nv) => nv.value.span(),
101 };
102
103 Ok(Self::new(value, span))
104 }
105
106 fn from_nested_meta(item: &crate::ast::NestedMeta) -> Result<Self> {
107 T::from_nested_meta(item)
108 .map(|value| Self::new(value, item.span()))
109 .map_err(|e| e.with_span(item))
110 }
111
112 fn from_value(literal: &syn::Lit) -> Result<Self> {
113 T::from_value(literal)
114 .map(|value| Self::new(value, literal.span()))
115 .map_err(|e| e.with_span(literal))
116 }
117
118 fn from_expr(expr: &syn::Expr) -> Result<Self> {
119 T::from_expr(expr)
120 .map(|value| Self::new(value, expr.span()))
121 .map_err(|e| e.with_span(expr))
122 }
123}
124
125spanned!(FromGenericParam, from_generic_param, syn::GenericParam);
126spanned!(FromGenerics, from_generics, syn::Generics);
127spanned!(FromTypeParam, from_type_param, syn::TypeParam);
128spanned!(FromDeriveInput, from_derive_input, syn::DeriveInput);
129spanned!(FromField, from_field, syn::Field);
130spanned!(FromVariant, from_variant, syn::Variant);
131
132impl<T: Spanned> From<T> for SpannedValue<T> {
133 fn from(value: T) -> Self {
134 let span = value.span();
135 SpannedValue::new(value, span)
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142 use proc_macro2::Span;
143
144 #[test]
146 fn deref() {
147 let test = SpannedValue::new("hello", Span::call_site());
148 assert_eq!("hello", test.trim());
149 }
150}