Safe Rust bindings for Apple's Core Spotlight framework on macOS.
Status: v0.3.0 adds a complete async API module with executor-agnostic futures for all completion-handler operations. See COVERAGE.md for the current SDK matrix and known caveats.
use corespotlight::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let index = CSSearchableIndex::new("doom-fish.demo")?;
let attributes = CSSearchableItemAttributeSet::new("public.plain-text")?;
attributes.set_title(Some("doom-fish corespotlight"))?;
attributes.set_display_name(Some("doom-fish"))?;
attributes.set_keywords(["doom-fish", "spotlight"])?;
let item = CSSearchableItem::new(
Some("doom-fish.corespotlight.demo"),
Some("doom-fish"),
&attributes,
)?;
index.index_searchable_items(&[item.clone()])?;
index.delete_searchable_items_with_identifiers(["doom-fish.corespotlight.demo"])?;
Ok(())
}CSSearchableIndexcreation, deletion, batching, client-state fetch, external-provider fetch, and delegate / request-handler attachmentCSSearchableItemrank comparison, mutable identifiers, expiration dates, update flags, and update-listener optionsCSSearchableItemAttributeSetgeneric typed field enums for strings, arrays, numbers, URLs, data, dates, people, and maps, plus convenience helpers for common fields andNSUserActivity.contentAttributeSetCSSearchQuery,CSUserQuery,CSSearchQueryContext,CSUserQueryContext,CSSuggestion, Core Spotlight version metadata, error domains, suggestion/action keys, and mailbox constants- Simulatable
CSSearchableIndexDelegate,CSIndexExtensionRequestHandler,CSImportExtension, andDefaultIndexExtensionRequestHandlerflows for integration tests and examples
When the async feature is enabled, the async_api module provides executor-agnostic futures for all completion-handler operations:
use corespotlight::async_api::AsyncCSSearchableIndex;
use corespotlight::CSSearchableIndex;
let index = CSSearchableIndex::default_searchable_index()?;
let items = vec![]; // Create your items
AsyncCSSearchableIndex::index_searchable_items(&index, &items).await?;Available async operations:
AsyncCSSearchableIndex::index_searchable_items— Index items asynchronouslyAsyncCSSearchableIndex::delete_searchable_items_with_identifiers— Delete items by identifierAsyncCSSearchableIndex::delete_searchable_items_with_domain_identifiers— Delete items by domainAsyncCSSearchableIndex::delete_all_searchable_items— Delete all itemsAsyncCSSearchableIndex::fetch_last_client_state— Fetch last client state (macOS 13+)
Enable with cargo build --features async or add to Cargo.toml:
corespotlight = { version = "0.3", features = ["async"] }cargo run --example 01_index_smoke
cargo run --example 02_attribute_fields
cargo run --example 03_query_settings
cargo run --example 04_delegate_simulation
cargo run --example 05_index_extension_request_handler
cargo run --example 06_default_index_extension_request_handler
cargo run --example 07_user_activity_import_extensionCSCustomAttributeKeyis exposed, but Apple validates custom key names against the current bundle identifier at runtime; command-line examples may not always be able to create them.CSUserQuery::user_engaged_with_itemandCSUserQuery::user_engaged_with_suggestioncurrently return a bridge error on the command-line bridge because Apple’s Swift overlay uses opaque wrapper types that are not yet surfaced to Rust.CSSearchableIndex::end_index_batch_with_expected_client_statecurrently rejects non-Noneexpected state values on the current SDK bridge; the limitation is documented in COVERAGE.md.
Licensed under either Apache-2.0 or MIT at your option.