summaryrefslogtreecommitdiffstats
path: root/vendor/zerovec-derive/src/make_varule.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/zerovec-derive/src/make_varule.rs')
-rw-r--r--vendor/zerovec-derive/src/make_varule.rs78
1 files changed, 51 insertions, 27 deletions
diff --git a/vendor/zerovec-derive/src/make_varule.rs b/vendor/zerovec-derive/src/make_varule.rs
index 62cf0d9db..56aa0b4f3 100644
--- a/vendor/zerovec-derive/src/make_varule.rs
+++ b/vendor/zerovec-derive/src/make_varule.rs
@@ -8,11 +8,11 @@ use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, ToTokens};
use syn::spanned::Spanned;
use syn::{
- parse_quote, AttributeArgs, Data, DeriveInput, Error, Field, Fields, GenericArgument, Ident,
- Lifetime, PathArguments, Type,
+ parse_quote, Data, DeriveInput, Error, Field, Fields, GenericArgument, Ident, Lifetime,
+ PathArguments, Type, TypePath,
};
-pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStream2 {
+pub fn make_varule_impl(ule_name: Ident, mut input: DeriveInput) -> TokenStream2 {
if input.generics.type_params().next().is_some()
|| input.generics.const_params().next().is_some()
|| input.generics.lifetimes().count() > 1
@@ -44,20 +44,11 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr
let lt = lt.map(|l| &l.lifetime);
- if attr.len() != 1 {
- return Error::new(
- input.span(),
- "#[make_ule] takes one argument for the name of the ULE type it produces",
- )
- .to_compile_error();
- }
- let arg = &attr[0];
- let ule_name: Ident = parse_quote!(#arg);
-
let name = &input.ident;
+ let input_span = input.span();
let fields = match input.data {
- Data::Struct(ref s) => &s.fields,
+ Data::Struct(ref mut s) => &mut s.fields,
_ => {
return Error::new(input.span(), "#[make_varule] must be applied to a struct")
.to_compile_error();
@@ -75,16 +66,32 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr
let mut sized_fields = vec![];
let mut unsized_fields = vec![];
+ let mut custom_varule_idents = vec![];
+
+ for field in fields.iter_mut() {
+ match utils::extract_field_attributes(&mut field.attrs) {
+ Ok(i) => custom_varule_idents.push(i),
+ Err(e) => return e.to_compile_error(),
+ }
+ }
+
for (i, field) in fields.iter().enumerate() {
- match UnsizedField::new(field, i) {
+ match UnsizedField::new(field, i, custom_varule_idents[i].clone()) {
Ok(o) => unsized_fields.push(o),
Err(_) => sized_fields.push(FieldInfo::new_for_field(field, i)),
}
}
if unsized_fields.is_empty() {
+ let last_field_index = fields.len() - 1;
let last_field = fields.iter().next_back().unwrap();
- let e = UnsizedField::new(last_field, fields.len() - 1).unwrap_err();
+
+ let e = UnsizedField::new(
+ last_field,
+ last_field_index,
+ custom_varule_idents[last_field_index].clone(),
+ )
+ .unwrap_err();
return Error::new(last_field.span(), e).to_compile_error();
}
@@ -112,10 +119,13 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr
let field_inits = utils::wrap_field_inits(&field_inits, fields);
let vis = &input.vis;
- let doc = format!("[`VarULE`](zerovec::ule::VarULE) type for {name}");
+ let doc = format!(
+ "[`VarULE`](zerovec::ule::VarULE) type for [`{name}`]. See [`{name}`] for documentation."
+ );
let varule_struct: DeriveInput = parse_quote!(
#[repr(#repr_attr)]
#[doc = #doc]
+ #[allow(missing_docs)]
#vis struct #ule_name #field_inits #semi
);
@@ -138,7 +148,7 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr
name,
&ule_name,
lt,
- input.span(),
+ input_span,
);
let eq_impl = quote!(
@@ -409,11 +419,13 @@ enum OwnULETy<'a> {
}
/// Represents the type of the last field of the struct
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug)]
enum UnsizedFieldKind<'a> {
Cow(OwnULETy<'a>),
ZeroVec(&'a Type),
VarZeroVec(&'a Type),
+ /// Custom VarULE type, and the identifier corresponding to the VarULE type
+ Custom(&'a TypePath, Ident),
// Generally you should be using the above ones for maximum zero-copy, but these will still work
Growable(OwnULETy<'a>),
@@ -568,9 +580,13 @@ impl<'a> UnsizedFields<'a> {
}
impl<'a> UnsizedField<'a> {
- fn new(field: &'a Field, index: usize) -> Result<Self, String> {
+ fn new(
+ field: &'a Field,
+ index: usize,
+ custom_varule_ident: Option<Ident>,
+ ) -> Result<Self, String> {
Ok(UnsizedField {
- kind: UnsizedFieldKind::new(&field.ty)?,
+ kind: UnsizedFieldKind::new(&field.ty, custom_varule_ident)?,
field: FieldInfo::new_for_field(field, index),
})
}
@@ -596,7 +612,10 @@ impl<'a> UnsizedField<'a> {
impl<'a> UnsizedFieldKind<'a> {
/// Construct a UnsizedFieldKind for the type of a UnsizedFieldKind if possible
- fn new(ty: &'a Type) -> Result<UnsizedFieldKind<'a>, String> {
+ fn new(
+ ty: &'a Type,
+ custom_varule_ident: Option<Ident>,
+ ) -> Result<UnsizedFieldKind<'a>, String> {
static PATH_TYPE_IDENTITY_ERROR: &str =
"Can only automatically detect corresponding VarULE types for path types \
that are Cow, ZeroVec, VarZeroVec, Box, String, or Vec";
@@ -607,6 +626,9 @@ impl<'a> UnsizedFieldKind<'a> {
match *ty {
Type::Reference(ref tyref) => OwnULETy::new(&tyref.elem, "reference").map(UnsizedFieldKind::Ref),
Type::Path(ref typath) => {
+ if let Some(custom_varule_ident) = custom_varule_ident {
+ return Ok(UnsizedFieldKind::Custom(typath, custom_varule_ident));
+ }
if typath.path.segments.len() != 1 {
return Err("Can only automatically detect corresponding VarULE types for \
path types with a single path segment".into());
@@ -678,6 +700,7 @@ impl<'a> UnsizedFieldKind<'a> {
let inner_ule = inner.varule_ty();
quote!(#inner_ule)
}
+ Self::Custom(_, ref name) => quote!(#name),
Self::ZeroVec(ref inner) => quote!(zerovec::ZeroSlice<#inner>),
Self::VarZeroVec(ref inner) => quote!(zerovec::VarZeroSlice<#inner>),
}
@@ -688,8 +711,8 @@ impl<'a> UnsizedFieldKind<'a> {
match *self {
Self::Ref(_) | Self::Cow(_) | Self::Growable(_) | Self::Boxed(_) => quote!(&*#value),
- Self::ZeroVec(_) => quote!(&*#value),
- Self::VarZeroVec(_) => quote!(&*#value),
+ Self::Custom(..) => quote!(&#value),
+ Self::ZeroVec(_) | Self::VarZeroVec(_) => quote!(&*#value),
}
}
@@ -701,15 +724,16 @@ impl<'a> UnsizedFieldKind<'a> {
| Self::Growable(ref inner)
| Self::Boxed(ref inner) => inner.varule_ty(),
- Self::ZeroVec(ty) => quote!(zerovec::ZeroSlice<#ty>),
- Self::VarZeroVec(ty) => quote!(zerovec::VarZeroSlice<#ty>),
+ Self::Custom(ref path, _) => quote!(#path),
+ Self::ZeroVec(ref ty) => quote!(zerovec::ZeroSlice<#ty>),
+ Self::VarZeroVec(ref ty) => quote!(zerovec::VarZeroSlice<#ty>),
}
}
fn has_zf(&self) -> bool {
matches!(
*self,
- Self::Ref(_) | Self::Cow(_) | Self::ZeroVec(_) | Self::VarZeroVec(_)
+ Self::Ref(_) | Self::Cow(_) | Self::ZeroVec(_) | Self::VarZeroVec(_) | Self::Custom(..)
)
}
}