Skip to content

Instantly share code, notes, and snippets.

@kennykerr
Created March 7, 2022 22:36
Show Gist options
  • Save kennykerr/8ea808321785897d8195b8db4d05d2e7 to your computer and use it in GitHub Desktop.
Save kennykerr/8ea808321785897d8195b8db4d05d2e7 to your computer and use it in GitHub Desktop.
use super::*;
#[derive(Default)]
pub struct Gen<'a> {
pub namespace: &'a str,
pub sys: bool,
pub flatten: bool,
pub cfg: bool,
pub doc: bool,
pub min_enum: bool,
pub min_inherit: bool,
pub min_xaml: bool,
pub windows_extern: bool,
}
impl Gen<'_> {
pub(crate) fn namespace(&self, namespace: &str) -> TokenStream {
if self.flatten || namespace == self.namespace {
quote! {}
} else {
let is_external = namespace.starts_with("Windows.") && !self.namespace.starts_with("Windows");
let mut relative = self.namespace.split('.').peekable();
let mut namespace = namespace.split('.').peekable();
while relative.peek() == namespace.peek() {
if relative.next().is_none() {
break;
}
namespace.next();
}
let mut tokens = TokenStream::new();
if is_external {
tokens.push_str("::windows::");
namespace.next();
} else {
for _ in 0..relative.count() {
tokens.push_str("super::");
}
}
for namespace in namespace {
tokens.push_str(namespace);
tokens.push_str("::");
}
tokens
}
}
pub fn doc(&self, cfg: &Cfg) -> TokenStream {
if !self.doc {
quote! {}
} else {
let mut tokens = format!("'{}'", self.to_feature(self.namespace));
let mut features = cfg.features(self.namespace);
// if self.windows_extern {
// features = features.into_iter().filter(|f| !f.starts_with("Windows.")).collect();
// }
for features in features {
tokens.push_str(&format!(", '{}'", self.to_feature(features)));
}
format!(r#"#[doc = "*Required features: {}*"]"#, tokens).into()
}
}
pub(crate) fn cfg(&self, cfg: &Cfg) -> TokenStream {
if !self.cfg {
quote! {}
} else {
let arches = cfg.arches();
let arch = match arches.len() {
0 => quote! {},
1 => {
quote! { #[cfg(#(target_arch = #arches),*)] }
}
_ => {
quote! { #[cfg(any(#(target_arch = #arches),*))] }
}
};
let mut features = cfg.features(self.namespace);
if self.windows_extern {
features = features.into_iter().filter(|f| !f.starts_with("Windows.")).collect();
}
let features = match features.len() {
0 => quote! {},
1 => {
let features = features.iter().cloned().map(|f| self.to_feature(f));
quote! { #[cfg(#(feature = #features)*)] }
}
_ => {
let features = features.iter().cloned().map(|f| self.to_feature(f));
quote! { #[cfg(all( #(feature = #features),* ))] }
}
};
quote! { #arch #features }
}
}
pub(crate) fn not_cfg(&self, cfg: &Cfg) -> TokenStream {
let mut features = cfg.features(self.namespace);
if !self.cfg || features.is_empty() {
quote! {}
} else {
if self.windows_extern {
features = features.into_iter().filter(|f| !f.starts_with("Windows.")).collect();
}
match features.len() {
0 => quote! {},
1 => {
let features = features.iter().cloned().map(|f| self.to_feature(f));
quote! { #[cfg(not(#(feature = #features)*))] }
}
_ => {
let features = features.iter().cloned().map(|f| self.to_feature(f));
quote! { #[cfg(not(all( #(feature = #features),* )))] }
}
}
}
}
fn to_feature(&self, name: &str) -> String {
let mut feature = String::new();
if self.windows_extern && name.starts_with("Windows.") {
feature.push_str("windows/");
}
for name in name.split('.').skip(1) {
feature.push_str(name);
feature.push('_');
}
if feature.is_empty() {
feature = name.to_string();
} else {
feature.truncate(feature.len() - 1);
}
feature
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment