mirror of https://github.com/rwf2/Rocket.git
Add codegen internal 'Ident::uniqueify()' method.
This makes an ident unique based on some or no metadata.
This commit is contained in:
parent
d21608ca7b
commit
41018a5112
|
@ -1,5 +1,7 @@
|
||||||
mod parse;
|
mod parse;
|
||||||
|
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
use proc_macro2::{TokenStream, Span};
|
use proc_macro2::{TokenStream, Span};
|
||||||
use devise::{Spanned, SpanWrapped, Result, FromMeta, Diagnostic};
|
use devise::{Spanned, SpanWrapped, Result, FromMeta, Diagnostic};
|
||||||
use devise::ext::TypeExt as _;
|
use devise::ext::TypeExt as _;
|
||||||
|
@ -8,9 +10,9 @@ use crate::{proc_macro2, syn};
|
||||||
use crate::proc_macro_ext::StringLit;
|
use crate::proc_macro_ext::StringLit;
|
||||||
use crate::syn_ext::{IdentExt, TypeExt as _};
|
use crate::syn_ext::{IdentExt, TypeExt as _};
|
||||||
use crate::http_codegen::{Method, Optional};
|
use crate::http_codegen::{Method, Optional};
|
||||||
|
|
||||||
use crate::attribute::param::Guard;
|
use crate::attribute::param::Guard;
|
||||||
use parse::{Route, Attribute, MethodAttribute};
|
|
||||||
|
use self::parse::{Route, Attribute, MethodAttribute};
|
||||||
|
|
||||||
impl Route {
|
impl Route {
|
||||||
pub fn guards(&self) -> impl Iterator<Item = &Guard> {
|
pub fn guards(&self) -> impl Iterator<Item = &Guard> {
|
||||||
|
@ -193,30 +195,20 @@ fn data_guard_decl(guard: &Guard) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn internal_uri_macro_decl(route: &Route) -> TokenStream {
|
fn internal_uri_macro_decl(route: &Route) -> TokenStream {
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
||||||
use std::collections::hash_map::DefaultHasher;
|
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
|
|
||||||
// Keep a global counter (+ thread ID later) to generate unique ids.
|
|
||||||
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
|
||||||
|
|
||||||
// FIXME: Is this the right order? Does order matter?
|
// FIXME: Is this the right order? Does order matter?
|
||||||
let uri_args = route.param_guards()
|
let uri_args = route.param_guards()
|
||||||
.chain(route.query_guards())
|
.chain(route.query_guards())
|
||||||
.map(|guard| (&guard.fn_ident, &guard.ty))
|
.map(|guard| (&guard.fn_ident, &guard.ty))
|
||||||
.map(|(ident, ty)| quote!(#ident: #ty));
|
.map(|(ident, ty)| quote!(#ident: #ty));
|
||||||
|
|
||||||
// Generate entropy based on the route's metadata.
|
// Generate a unique macro name based on the route's metadata.
|
||||||
let mut hasher = DefaultHasher::new();
|
|
||||||
route.handler.sig.ident.hash(&mut hasher);
|
|
||||||
route.attr.uri.path().hash(&mut hasher);
|
|
||||||
route.attr.uri.query().hash(&mut hasher);
|
|
||||||
std::process::id().hash(&mut hasher);
|
|
||||||
std::thread::current().id().hash(&mut hasher);
|
|
||||||
COUNTER.fetch_add(1, Ordering::AcqRel).hash(&mut hasher);
|
|
||||||
|
|
||||||
let macro_name = route.handler.sig.ident.prepend(crate::URI_MACRO_PREFIX);
|
let macro_name = route.handler.sig.ident.prepend(crate::URI_MACRO_PREFIX);
|
||||||
let inner_macro_name = macro_name.append(&hasher.finish().to_string());
|
let inner_macro_name = macro_name.uniqueify_with(|mut hasher| {
|
||||||
|
route.handler.sig.ident.hash(&mut hasher);
|
||||||
|
route.attr.uri.path().hash(&mut hasher);
|
||||||
|
route.attr.uri.query().hash(&mut hasher)
|
||||||
|
});
|
||||||
|
|
||||||
let route_uri = route.attr.uri.to_string();
|
let route_uri = route.attr.uri.to_string();
|
||||||
|
|
||||||
quote_spanned! { Span::call_site() =>
|
quote_spanned! { Span::call_site() =>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Extensions to `syn` types.
|
//! Extensions to `syn` types.
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
use crate::syn::{self, Ident, ext::IdentExt as _, visit::Visit};
|
use crate::syn::{self, Ident, ext::IdentExt as _, visit::Visit};
|
||||||
use crate::proc_macro2::Span;
|
use crate::proc_macro2::Span;
|
||||||
|
@ -10,6 +11,7 @@ pub trait IdentExt {
|
||||||
fn append(&self, string: &str) -> syn::Ident;
|
fn append(&self, string: &str) -> syn::Ident;
|
||||||
fn with_span(self, span: Span) -> syn::Ident;
|
fn with_span(self, span: Span) -> syn::Ident;
|
||||||
fn rocketized(&self) -> syn::Ident;
|
fn rocketized(&self) -> syn::Ident;
|
||||||
|
fn uniqueify_with<F: FnMut(&mut dyn Hasher)>(&self, f: F) -> syn::Ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ReturnTypeExt {
|
pub trait ReturnTypeExt {
|
||||||
|
@ -61,6 +63,23 @@ impl IdentExt for syn::Ident {
|
||||||
fn rocketized(&self) -> syn::Ident {
|
fn rocketized(&self) -> syn::Ident {
|
||||||
self.prepend(crate::ROCKET_IDENT_PREFIX)
|
self.prepend(crate::ROCKET_IDENT_PREFIX)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn uniqueify_with<F: FnMut(&mut dyn Hasher)>(&self, mut f: F) -> syn::Ident {
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
|
||||||
|
// Keep a global counter (+ thread ID later) to generate unique ids.
|
||||||
|
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
self.hash(&mut hasher);
|
||||||
|
std::process::id().hash(&mut hasher);
|
||||||
|
std::thread::current().id().hash(&mut hasher);
|
||||||
|
COUNTER.fetch_add(1, Ordering::AcqRel).hash(&mut hasher);
|
||||||
|
f(&mut hasher);
|
||||||
|
|
||||||
|
self.append(&format!("_{}", hasher.finish()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReturnTypeExt for syn::ReturnType {
|
impl ReturnTypeExt for syn::ReturnType {
|
||||||
|
|
Loading…
Reference in New Issue