use std::collections::BTreeSet;
use crate::{is_str, is_byte_slice};
use crate::attrs::Idx;
pub fn gen_lifetime() -> syn::LifetimeParam {
syn::parse_quote!('bytes)
}
pub fn add_lifetime(g: &syn::Generics, l: syn::LifetimeParam) -> syn::Generics {
let mut g2 = g.clone();
g2.params = Some(l.into()).into_iter().chain(g2.params).collect();
g2
}
pub fn lifetimes_to_constrain<'a, I>(types: I) -> BTreeSet<syn::Lifetime>
where
I: Iterator<Item = (&'a Idx, Option<&'a BTreeSet<syn::Lifetime>>, &'a syn::Type)>
{
fn tyref_lifetime(ty: &syn::Type, pred: impl FnOnce(&syn::Type) -> bool) -> Option<syn::Lifetime> {
if let syn::Type::Reference(p) = ty && pred(&p.elem) {
return p.lifetime.clone()
}
None
}
fn get_lifetimes(ty: &syn::Type, set: &mut BTreeSet<syn::Lifetime>, filter: &BTreeSet<syn::Lifetime>) {
match ty {
syn::Type::Array(t) => get_lifetimes(&t.elem, set, filter),
syn::Type::Slice(t) => get_lifetimes(&t.elem, set, filter),
syn::Type::Paren(t) => get_lifetimes(&t.elem, set, filter),
syn::Type::Group(t) => get_lifetimes(&t.elem, set, filter),
syn::Type::Ptr(t) => get_lifetimes(&t.elem, set, filter),
syn::Type::Reference(t) => {
if let Some(l) = &t.lifetime && (filter.is_empty() || filter.contains(l)) {
set.insert(l.clone());
}
get_lifetimes(&t.elem, set, filter)
}
syn::Type::Tuple(t) => {
for t in &t.elems {
get_lifetimes(t, set, filter)
}
}
syn::Type::Path(t) => {
for s in &t.path.segments {
if let syn::PathArguments::AngleBracketed(b) = &s.arguments {
for a in &b.args {
match a {
syn::GenericArgument::Type(t) => get_lifetimes(t, set, filter),
syn::GenericArgument::AssocType(b) => get_lifetimes(&b.ty, set, filter),
syn::GenericArgument::Lifetime(l) => {
if filter.is_empty() || filter.contains(l) {
set.insert(l.clone());
}
}
_ => {}
}
}
}
}
}
_ => {}
}
}
fn option_lifetime(ty: &syn::Type, pred: impl FnOnce(&syn::Type) -> bool) -> Option<syn::Lifetime> {
if let syn::Type::Path(t) = ty
&& let Some(s) = t.path.segments.last()
&& s.ident == "Option"
&& let syn::PathArguments::AngleBracketed(b) = &s.arguments
&& b.args.len() == 1
&& let syn::GenericArgument::Type(syn::Type::Reference(ty)) = &b.args[0]
&& pred(&ty.elem)
{
return ty.lifetime.clone()
}
None
}
let mut set = BTreeSet::new();
for (i, l, t) in types {
if let Some(l) = tyref_lifetime(t, is_str) {
set.insert(l);
continue
}
if let Some(l) = tyref_lifetime(t, is_byte_slice) {
set.insert(l);
continue
}
if let Some(l) = option_lifetime(t, is_str) {
set.insert(l);
continue
}
if let Some(l) = option_lifetime(t, is_byte_slice) {
set.insert(l);
continue
}
if let Some(l) = l {
get_lifetimes(t, &mut set, l)
}
if i.is_b() {
get_lifetimes(t, &mut set, &BTreeSet::new())
}
}
set
}