Use the contains method on string slices (&str) or String types, as it returns a boolean indicating whether the substring exists. This method works directly on both owned String values and borrowed &str references without needing conversion.
fn main() {
let text = "Rust is awesome";
let search = "awesome";
// Check if text contains the substring
if text.contains(search) {
println!("Found it!");
}
// Works with string literals too
let has_rust = "Rust is awesome".contains("Rust");
println!("{}", has_rust); // true
}
For more complex scenarios like case-insensitive matching or checking multiple substrings, you can combine contains with string manipulation methods or use the matches crate for pattern matching.
fn main() {
let text = "Rust is Awesome";
// Case-insensitive check
let found = text.to_lowercase().contains("awesome");
println!("{}", found); // true
// Check multiple substrings
let keywords = ["rust", "go", "python"];
let has_keyword = keywords.iter().any(|k| text.to_lowercase().contains(k));
println!("{}", has_keyword); // true
}
If you need to find the position of the substring rather than just checking existence, use the find method which returns an Option<usize> containing the starting index or None if not found.
fn main() {
let text = "Rust is awesome";
if let Some(pos) = text.find("awesome") {
println!("Found at index: {}", pos);
} else {
println!("Not found");
}
}
The contains method is the most efficient and idiomatic way to check for substring presence in Rust. It's implemented directly on string types and handles UTF-8 correctly, making it safe for international text. For performance-critical code with many repeated searches, consider using specialized crates like aho-corasick which implement efficient multi-pattern matching algorithms.