Skip to main content

decycle_impl/
lib.rs

1use syn::*;
2
3pub mod finalize;
4mod process_module;
5mod process_trait;
6
7pub use proc_macro_error;
8pub use type_leak;
9
10pub use process_module::process_module;
11pub use process_trait::process_trait;
12
13fn is_decycle_attribute(attr: &Attribute) -> bool {
14    let path = &attr.path();
15    path.is_ident("decycle")
16        || (path.segments.len() == 2
17            && (&path.segments[0].ident == "decycle"
18                || is_renamed_decycle_crate(&path.segments[0].ident))
19            && &path.segments[1].ident == "decycle")
20}
21
22fn is_renamed_decycle_crate(ident: &proc_macro2::Ident) -> bool {
23    let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_default();
24
25    if let Ok(cargo_toml) = std::fs::read_to_string(format!("{}/Cargo.toml", manifest_dir)) {
26        if cargo_toml.contains(&format!("{} = {{ package = \"decycle\"", ident))
27            || cargo_toml.contains(&format!("{} = {{ package = 'decycle'", ident))
28        {
29            return true;
30        }
31    }
32
33    false
34}
35
36fn ident_to_path(ident: &Ident) -> Path {
37    Path {
38        leading_colon: None,
39        segments: core::iter::once(PathSegment {
40            ident: ident.clone(),
41            arguments: PathArguments::None,
42        })
43        .collect(),
44    }
45}
46
47fn get_random() -> u64 {
48    identity_to_u64(&get_crate_identity())
49}
50
51fn get_crate_identity() -> String {
52    "decycle".to_string()
53}
54
55fn identity_to_u64(value: &str) -> u64 {
56    // Deterministic FNV-1a hash for stable crate-local randomness.
57    const FNV_OFFSET: u64 = 0xcbf29ce484222325;
58    const FNV_PRIME: u64 = 0x100000001b3;
59    let mut hash = FNV_OFFSET;
60    for byte in value.as_bytes() {
61        hash ^= u64::from(*byte);
62        hash = hash.wrapping_mul(FNV_PRIME);
63    }
64    hash
65}