diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:25 +0000 |
commit | 5363f350887b1e5b5dd21a86f88c8af9d7fea6da (patch) | |
tree | 35ca005eb6e0e9a1ba3bb5dbc033209ad445dc17 /vendor/strum_macros/src/macros/strings | |
parent | Adding debian version 1.66.0+dfsg1-1. (diff) | |
download | rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.tar.xz rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/strum_macros/src/macros/strings')
-rw-r--r-- | vendor/strum_macros/src/macros/strings/as_ref_str.rs | 117 | ||||
-rw-r--r-- | vendor/strum_macros/src/macros/strings/display.rs | 51 | ||||
-rw-r--r-- | vendor/strum_macros/src/macros/strings/from_string.rs | 180 | ||||
-rw-r--r-- | vendor/strum_macros/src/macros/strings/mod.rs | 4 | ||||
-rw-r--r-- | vendor/strum_macros/src/macros/strings/to_string.rs | 51 |
5 files changed, 403 insertions, 0 deletions
diff --git a/vendor/strum_macros/src/macros/strings/as_ref_str.rs b/vendor/strum_macros/src/macros/strings/as_ref_str.rs new file mode 100644 index 000000000..4dfdc4b80 --- /dev/null +++ b/vendor/strum_macros/src/macros/strings/as_ref_str.rs @@ -0,0 +1,117 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{parse_quote, Data, DeriveInput, Fields}; + +use crate::helpers::{non_enum_error, HasStrumVariantProperties, HasTypeProperties}; + +fn get_arms(ast: &DeriveInput) -> syn::Result<Vec<TokenStream>> { + let name = &ast.ident; + let mut arms = Vec::new(); + let variants = match &ast.data { + Data::Enum(v) => &v.variants, + _ => return Err(non_enum_error()), + }; + + let type_properties = ast.get_type_properties()?; + + for variant in variants { + let ident = &variant.ident; + let variant_properties = variant.get_variant_properties()?; + + if variant_properties.disabled.is_some() { + continue; + } + + // Look at all the serialize attributes. + // Use `to_string` attribute (not `as_ref_str` or something) to keep things consistent + // (i.e. always `enum.as_ref().to_string() == enum.to_string()`). + let output = variant_properties.get_preferred_name(type_properties.case_style); + let params = match variant.fields { + Fields::Unit => quote! {}, + Fields::Unnamed(..) => quote! { (..) }, + Fields::Named(..) => quote! { {..} }, + }; + + arms.push(quote! { #name::#ident #params => #output }); + } + + if arms.len() < variants.len() { + arms.push(quote! { + _ => panic!( + "AsRef::<str>::as_ref() or AsStaticRef::<str>::as_static() \ + called on disabled variant.", + ) + }); + } + + Ok(arms) +} + +pub fn as_ref_str_inner(ast: &DeriveInput) -> syn::Result<TokenStream> { + let name = &ast.ident; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + let arms = get_arms(ast)?; + Ok(quote! { + impl #impl_generics ::core::convert::AsRef<str> for #name #ty_generics #where_clause { + fn as_ref(&self) -> &str { + match *self { + #(#arms),* + } + } + } + }) +} + +pub enum GenerateTraitVariant { + AsStaticStr, + From, +} + +pub fn as_static_str_inner( + ast: &DeriveInput, + trait_variant: &GenerateTraitVariant, +) -> syn::Result<TokenStream> { + let name = &ast.ident; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + let arms = get_arms(ast)?; + let type_properties = ast.get_type_properties()?; + let strum_module_path = type_properties.crate_module_path(); + + let mut generics = ast.generics.clone(); + generics + .params + .push(syn::GenericParam::Lifetime(syn::LifetimeDef::new( + parse_quote!('_derivative_strum), + ))); + let (impl_generics2, _, _) = generics.split_for_impl(); + let arms2 = arms.clone(); + let arms3 = arms.clone(); + + Ok(match trait_variant { + GenerateTraitVariant::AsStaticStr => quote! { + impl #impl_generics #strum_module_path::AsStaticRef<str> for #name #ty_generics #where_clause { + fn as_static(&self) -> &'static str { + match *self { + #(#arms),* + } + } + } + }, + GenerateTraitVariant::From => quote! { + impl #impl_generics ::core::convert::From<#name #ty_generics> for &'static str #where_clause { + fn from(x: #name #ty_generics) -> &'static str { + match x { + #(#arms2),* + } + } + } + impl #impl_generics2 ::core::convert::From<&'_derivative_strum #name #ty_generics> for &'static str #where_clause { + fn from(x: &'_derivative_strum #name #ty_generics) -> &'static str { + match *x { + #(#arms3),* + } + } + } + }, + }) +} diff --git a/vendor/strum_macros/src/macros/strings/display.rs b/vendor/strum_macros/src/macros/strings/display.rs new file mode 100644 index 000000000..82a34b0df --- /dev/null +++ b/vendor/strum_macros/src/macros/strings/display.rs @@ -0,0 +1,51 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Data, DeriveInput, Fields}; + +use crate::helpers::{non_enum_error, HasStrumVariantProperties, HasTypeProperties}; + +pub fn display_inner(ast: &DeriveInput) -> syn::Result<TokenStream> { + let name = &ast.ident; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + let variants = match &ast.data { + Data::Enum(v) => &v.variants, + _ => return Err(non_enum_error()), + }; + + let type_properties = ast.get_type_properties()?; + + let mut arms = Vec::new(); + for variant in variants { + let ident = &variant.ident; + let variant_properties = variant.get_variant_properties()?; + + if variant_properties.disabled.is_some() { + continue; + } + + // Look at all the serialize attributes. + let output = variant_properties.get_preferred_name(type_properties.case_style); + + let params = match variant.fields { + Fields::Unit => quote! {}, + Fields::Unnamed(..) => quote! { (..) }, + Fields::Named(..) => quote! { {..} }, + }; + + arms.push(quote! { #name::#ident #params => f.pad(#output) }); + } + + if arms.len() < variants.len() { + arms.push(quote! { _ => panic!("fmt() called on disabled variant.") }); + } + + Ok(quote! { + impl #impl_generics ::core::fmt::Display for #name #ty_generics #where_clause { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::result::Result<(), ::core::fmt::Error> { + match *self { + #(#arms),* + } + } + } + }) +} diff --git a/vendor/strum_macros/src/macros/strings/from_string.rs b/vendor/strum_macros/src/macros/strings/from_string.rs new file mode 100644 index 000000000..2d2559174 --- /dev/null +++ b/vendor/strum_macros/src/macros/strings/from_string.rs @@ -0,0 +1,180 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Data, DeriveInput, Fields}; + +use crate::helpers::{ + non_enum_error, occurrence_error, HasStrumVariantProperties, HasTypeProperties, +}; + +pub fn from_string_inner(ast: &DeriveInput) -> syn::Result<TokenStream> { + let name = &ast.ident; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + let variants = match &ast.data { + Data::Enum(v) => &v.variants, + _ => return Err(non_enum_error()), + }; + + let type_properties = ast.get_type_properties()?; + let strum_module_path = type_properties.crate_module_path(); + + let mut default_kw = None; + let mut default = + quote! { ::core::result::Result::Err(#strum_module_path::ParseError::VariantNotFound) }; + + let mut phf_exact_match_arms = Vec::new(); + let mut standard_match_arms = Vec::new(); + for variant in variants { + let ident = &variant.ident; + let variant_properties = variant.get_variant_properties()?; + + if variant_properties.disabled.is_some() { + continue; + } + + if let Some(kw) = variant_properties.default { + if let Some(fst_kw) = default_kw { + return Err(occurrence_error(fst_kw, kw, "default")); + } + + match &variant.fields { + Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {} + _ => { + return Err(syn::Error::new_spanned( + variant, + "Default only works on newtype structs with a single String field", + )) + } + } + + default_kw = Some(kw); + default = quote! { + ::core::result::Result::Ok(#name::#ident(s.into())) + }; + continue; + } + + let params = match &variant.fields { + Fields::Unit => quote! {}, + Fields::Unnamed(fields) => { + let defaults = + ::core::iter::repeat(quote!(Default::default())).take(fields.unnamed.len()); + quote! { (#(#defaults),*) } + } + Fields::Named(fields) => { + let fields = fields + .named + .iter() + .map(|field| field.ident.as_ref().unwrap()); + quote! { {#(#fields: Default::default()),*} } + } + }; + + let is_ascii_case_insensitive = variant_properties + .ascii_case_insensitive + .unwrap_or(type_properties.ascii_case_insensitive); + + // If we don't have any custom variants, add the default serialized name. + for serialization in variant_properties.get_serializations(type_properties.case_style) { + if type_properties.use_phf { + phf_exact_match_arms.push(quote! { #serialization => #name::#ident #params, }); + + if is_ascii_case_insensitive { + // Store the lowercase and UPPERCASE variants in the phf map to capture + let ser_string = serialization.value(); + + let lower = + syn::LitStr::new(&ser_string.to_ascii_lowercase(), serialization.span()); + let upper = + syn::LitStr::new(&ser_string.to_ascii_uppercase(), serialization.span()); + phf_exact_match_arms.push(quote! { #lower => #name::#ident #params, }); + phf_exact_match_arms.push(quote! { #upper => #name::#ident #params, }); + standard_match_arms.push(quote! { s if s.eq_ignore_ascii_case(#serialization) => #name::#ident #params, }); + } + } else { + standard_match_arms.push(if !is_ascii_case_insensitive { + quote! { #serialization => #name::#ident #params, } + } else { + quote! { s if s.eq_ignore_ascii_case(#serialization) => #name::#ident #params, } + }); + } + } + } + + let phf_body = if phf_exact_match_arms.is_empty() { + quote!() + } else { + quote! { + use #strum_module_path::_private_phf_reexport_for_macro_if_phf_feature as phf; + static PHF: phf::Map<&'static str, #name> = phf::phf_map! { + #(#phf_exact_match_arms)* + }; + if let Some(value) = PHF.get(s).cloned() { + return ::core::result::Result::Ok(value); + } + } + }; + let standard_match_body = if standard_match_arms.is_empty() { + default + } else { + quote! { + ::core::result::Result::Ok(match s { + #(#standard_match_arms)* + _ => return #default, + }) + } + }; + + let from_str = quote! { + #[allow(clippy::use_self)] + impl #impl_generics ::core::str::FromStr for #name #ty_generics #where_clause { + type Err = #strum_module_path::ParseError; + fn from_str(s: &str) -> ::core::result::Result< #name #ty_generics , <Self as ::core::str::FromStr>::Err> { + #phf_body + #standard_match_body + } + } + }; + + let try_from_str = try_from_str( + name, + &impl_generics, + &ty_generics, + where_clause, + &strum_module_path, + ); + + Ok(quote! { + #from_str + #try_from_str + }) +} + +#[rustversion::before(1.34)] +fn try_from_str( + _name: &proc_macro2::Ident, + _impl_generics: &syn::ImplGenerics, + _ty_generics: &syn::TypeGenerics, + _where_clause: Option<&syn::WhereClause>, + _strum_module_path: &syn::Path, +) -> TokenStream { + Default::default() +} + +#[rustversion::since(1.34)] +fn try_from_str( + name: &proc_macro2::Ident, + impl_generics: &syn::ImplGenerics, + ty_generics: &syn::TypeGenerics, + where_clause: Option<&syn::WhereClause>, + strum_module_path: &syn::Path, +) -> TokenStream { + quote! { + #[allow(clippy::use_self)] + impl #impl_generics ::core::convert::TryFrom<&str> for #name #ty_generics #where_clause { + type Error = #strum_module_path::ParseError; + fn try_from(s: &str) -> ::core::result::Result< #name #ty_generics , <Self as ::core::convert::TryFrom<&str>>::Error> { + ::core::str::FromStr::from_str(s) + } + } + } +} diff --git a/vendor/strum_macros/src/macros/strings/mod.rs b/vendor/strum_macros/src/macros/strings/mod.rs new file mode 100644 index 000000000..e416f4b3b --- /dev/null +++ b/vendor/strum_macros/src/macros/strings/mod.rs @@ -0,0 +1,4 @@ +pub mod as_ref_str; +pub mod display; +pub mod from_string; +pub mod to_string; diff --git a/vendor/strum_macros/src/macros/strings/to_string.rs b/vendor/strum_macros/src/macros/strings/to_string.rs new file mode 100644 index 000000000..7e4c48380 --- /dev/null +++ b/vendor/strum_macros/src/macros/strings/to_string.rs @@ -0,0 +1,51 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Data, DeriveInput, Fields}; + +use crate::helpers::{non_enum_error, HasStrumVariantProperties, HasTypeProperties}; + +pub fn to_string_inner(ast: &DeriveInput) -> syn::Result<TokenStream> { + let name = &ast.ident; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); + let variants = match &ast.data { + Data::Enum(v) => &v.variants, + _ => return Err(non_enum_error()), + }; + + let type_properties = ast.get_type_properties()?; + let mut arms = Vec::new(); + for variant in variants { + let ident = &variant.ident; + let variant_properties = variant.get_variant_properties()?; + + if variant_properties.disabled.is_some() { + continue; + } + + // Look at all the serialize attributes. + let output = variant_properties.get_preferred_name(type_properties.case_style); + + let params = match variant.fields { + Fields::Unit => quote! {}, + Fields::Unnamed(..) => quote! { (..) }, + Fields::Named(..) => quote! { {..} }, + }; + + arms.push(quote! { #name::#ident #params => ::std::string::String::from(#output) }); + } + + if arms.len() < variants.len() { + arms.push(quote! { _ => panic!("to_string() called on disabled variant.") }); + } + + Ok(quote! { + #[allow(clippy::use_self)] + impl #impl_generics ::std::string::ToString for #name #ty_generics #where_clause { + fn to_string(&self) -> ::std::string::String { + match *self { + #(#arms),* + } + } + } + }) +} |