Implement From for structs

This commit is contained in:
David Tolnay 2019-10-12 17:03:11 -07:00
parent 03e77b3d2b
commit 946be606a9
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
2 changed files with 26 additions and 0 deletions

View File

@ -89,12 +89,25 @@ fn impl_struct(input: Struct) -> TokenStream {
} }
}); });
let from_impl = input.from_field().map(|from_field| {
let member = &from_field.member;
let from = from_field.ty;
quote! {
impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
fn from(source: #from) -> Self {
#ty { #member: source }
}
}
}
});
quote! { quote! {
impl #impl_generics std::error::Error for #ty #ty_generics #where_clause { impl #impl_generics std::error::Error for #ty #ty_generics #where_clause {
#source_method #source_method
#backtrace_method #backtrace_method
} }
#display_impl #display_impl
#from_impl
} }
} }

View File

@ -2,6 +2,10 @@ use crate::ast::{Enum, Field, Struct, Variant};
use syn::{Member, Type}; use syn::{Member, Type};
impl Struct<'_> { impl Struct<'_> {
pub(crate) fn from_field(&self) -> Option<&Field> {
from_field(&self.fields)
}
pub(crate) fn source_field(&self) -> Option<&Field> { pub(crate) fn source_field(&self) -> Option<&Field> {
source_field(&self.fields) source_field(&self.fields)
} }
@ -43,6 +47,15 @@ impl Variant<'_> {
} }
} }
fn from_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
for field in fields {
if field.attrs.from.is_some() {
return Some(&field);
}
}
None
}
fn source_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> { fn source_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
for field in fields { for field in fields {
if field.attrs.from.is_some() || field.attrs.source.is_some() { if field.attrs.from.is_some() || field.attrs.source.is_some() {