pub fn is_integer_type(name: &str) -> bool {
matches!(
name,
"i8" | "i16"
| "i32"
| "i64"
| "i128"
| "isize"
| "u8"
| "u16"
| "u32"
| "u64"
| "u128"
| "usize"
)
}
pub fn is_float_type(name: &str) -> bool {
matches!(name, "f32" | "f64")
}
pub fn is_numeric_type(name: &str) -> bool {
is_integer_type(name) || is_float_type(name)
}
pub fn is_copy_primitive(name: &str) -> bool {
is_numeric_type(name) || matches!(name, "bool" | "char")
}
pub fn is_numeric_suffix(name: &str) -> bool {
matches!(
name,
"u64" | "i64" | "u32" | "i32" | "u16" | "i16" | "u8" | "i8" | "usize" | "isize"
)
}
pub fn is_prelude_or_primitive(name: &str) -> bool {
is_copy_primitive(name) || matches!(name, "str" | "string" | "String" | "Self" | "self" | "()")
}
pub fn is_type_copy_with_registries(
ty: &crate::parser::ast::types::Type,
copy_structs: &std::collections::HashSet<String>,
copy_enums: &std::collections::HashSet<String>,
) -> bool {
use crate::parser::ast::types::Type;
match ty {
Type::Int | Type::Int32 | Type::Uint | Type::Float | Type::Bool => true,
Type::Reference(_) => true,
Type::MutableReference(_) => false,
Type::Tuple(types) => types
.iter()
.all(|t| is_type_copy_with_registries(t, copy_structs, copy_enums)),
Type::Option(inner) => is_type_copy_with_registries(inner, copy_structs, copy_enums),
Type::Result(ok, err) => {
is_type_copy_with_registries(ok, copy_structs, copy_enums)
&& is_type_copy_with_registries(err, copy_structs, copy_enums)
}
Type::Array(inner, _) => is_type_copy_with_registries(inner, copy_structs, copy_enums),
Type::Vec(_) | Type::String => false,
Type::RawPointer { pointee, .. } => {
is_type_copy_with_registries(pointee.as_ref(), copy_structs, copy_enums)
}
Type::FunctionPointer { .. } => true,
Type::Custom(name) => {
copy_structs.contains(name) || copy_enums.contains(name) || is_copy_primitive(name)
}
_ => false,
}
}
pub fn is_stdlib_container(name: &str) -> bool {
matches!(
name,
"Vec"
| "Option"
| "Result"
| "HashMap"
| "HashSet"
| "BTreeMap"
| "BTreeSet"
| "Box"
| "Arc"
| "Rc"
| "RefCell"
| "Cell"
| "Mutex"
| "RwLock"
| "Weak"
| "Pin"
| "PhantomData"
| "NonNull"
| "VecDeque"
| "BinaryHeap"
| "LinkedList"
| "SmallVec"
| "Cow"
| "Iter"
| "Slice"
| "Signal"
)
}
pub fn is_stdlib_collection_or_wrapper(ty: &crate::parser::ast::types::Type) -> bool {
use crate::parser::ast::types::Type;
match ty {
Type::Vec(_) | Type::Option(_) | Type::Result(_, _) | Type::String => true,
Type::Parameterized(name, _) | Type::Custom(name) => is_stdlib_container(name),
Type::Array(_, _) => true,
_ => false,
}
}
pub fn is_large_collection(name: &str) -> bool {
matches!(
name,
"HashMap" | "BTreeMap" | "HashSet" | "BTreeSet" | "IndexMap"
)
}
pub fn is_medium_collection(name: &str) -> bool {
matches!(name, "Vec" | "VecDeque" | "LinkedList")
}
pub fn is_map_type(name: &str) -> bool {
matches!(name, "HashMap" | "BTreeMap" | "IndexMap" | "Map")
}
pub fn is_heap_container(name: &str) -> bool {
matches!(name, "Vec" | "HashMap" | "String")
}
pub fn has_significant_drop(name: &str) -> bool {
matches!(
name,
"Mutex"
| "RwLock"
| "File"
| "TcpStream"
| "UdpSocket"
| "Channel"
| "Receiver"
| "Sender"
| "JoinHandle"
| "MutexGuard"
| "RwLockReadGuard"
| "RwLockWriteGuard"
)
}
pub fn is_consuming_operator_trait(name: &str) -> bool {
let base = name.rsplit("::").next().unwrap_or(name);
matches!(
base,
"Add"
| "Sub"
| "Mul"
| "Div"
| "Rem"
| "Neg"
| "Not"
| "BitAnd"
| "BitOr"
| "BitXor"
| "Shl"
| "Shr"
)
}
pub fn is_consuming_conversion_trait(name: &str) -> bool {
let base = name.rsplit("::").next().unwrap_or(name);
matches!(base, "Into" | "From" | "TryInto" | "TryFrom")
}
pub fn is_owned_self_trait(name: &str) -> bool {
is_consuming_operator_trait(name) || is_consuming_conversion_trait(name)
}
pub fn is_ref_receiver_trait(name: &str) -> bool {
let base = name.rsplit("::").next().unwrap_or(name);
matches!(
base,
"Display"
| "Debug"
| "Hash"
| "PartialEq"
| "Eq"
| "PartialOrd"
| "Ord"
| "Clone"
| "Copy"
| "Default"
| "Iterator"
| "IntoIterator"
| "AsRef"
| "Deref"
)
}
pub fn is_constructor_name(name: &str) -> bool {
matches!(
name,
"new"
| "default"
| "from"
| "from_str"
| "from_bytes"
| "with_capacity"
| "empty"
| "zero"
| "one"
)
}
pub fn is_ownership_producing_method(name: &str) -> bool {
matches!(name, "clone" | "to_owned" | "to_string" | "into_iter")
}
pub fn is_float_receiver_method(name: &str) -> bool {
matches!(
name,
"clamp"
| "max"
| "min"
| "abs"
| "copysign"
| "recip"
| "to_degrees"
| "to_radians"
| "signum"
| "powf"
| "powi"
| "sqrt"
| "cbrt"
| "log"
| "log2"
| "log10"
| "exp"
| "exp2"
| "sin"
| "cos"
| "tan"
| "asin"
| "acos"
| "atan"
| "atan2"
| "sinh"
| "cosh"
| "tanh"
| "ceil"
| "floor"
| "round"
| "fract"
| "trunc"
| "hypot"
| "mul_add"
| "ln"
| "fma"
)
}
pub fn rust_type_to_windjammer(rust_type: &str) -> &str {
match rust_type {
"i32" | "i64" | "isize" => "int",
"u32" | "u64" | "usize" => "uint",
"f32" | "f64" => "float",
"&str" | "String" => "string",
"bool" => "bool",
"()" => "void",
other => other,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_integer_types() {
assert!(is_integer_type("i32"));
assert!(is_integer_type("usize"));
assert!(!is_integer_type("f32"));
assert!(!is_integer_type("bool"));
assert!(!is_integer_type("String"));
}
#[test]
fn test_copy_primitives() {
assert!(is_copy_primitive("i32"));
assert!(is_copy_primitive("f64"));
assert!(is_copy_primitive("bool"));
assert!(is_copy_primitive("char"));
assert!(!is_copy_primitive("String"));
assert!(!is_copy_primitive("Vec"));
}
#[test]
fn test_stdlib_containers() {
assert!(is_stdlib_container("Vec"));
assert!(is_stdlib_container("HashMap"));
assert!(is_stdlib_container("Option"));
assert!(!is_stdlib_container("MyStruct"));
}
#[test]
fn test_trait_classification() {
assert!(is_consuming_operator_trait("Add"));
assert!(is_consuming_operator_trait("std::ops::Sub"));
assert!(!is_consuming_operator_trait("Display"));
assert!(is_ref_receiver_trait("Debug"));
assert!(is_ref_receiver_trait("Clone"));
assert!(!is_ref_receiver_trait("Add"));
assert!(is_owned_self_trait("Into"));
assert!(is_owned_self_trait("Add"));
assert!(!is_owned_self_trait("Display"));
}
#[test]
fn test_constructor_names() {
assert!(is_constructor_name("new"));
assert!(is_constructor_name("default"));
assert!(is_constructor_name("from"));
assert!(!is_constructor_name("update"));
}
#[test]
fn test_prelude_or_primitive() {
assert!(is_prelude_or_primitive("i32"));
assert!(is_prelude_or_primitive("String"));
assert!(is_prelude_or_primitive("Self"));
assert!(!is_prelude_or_primitive("MyType"));
}
#[test]
fn test_float_methods() {
assert!(is_float_receiver_method("clamp"));
assert!(is_float_receiver_method("sin"));
assert!(!is_float_receiver_method("push"));
}
#[test]
fn test_significant_drop() {
assert!(has_significant_drop("Mutex"));
assert!(has_significant_drop("File"));
assert!(!has_significant_drop("Vec"));
}
}