mindat-rs

Crates.iomindat-rs
lib.rsmindat-rs
version0.1.0
created_at2025-12-28 03:00:58.179022+00
updated_at2025-12-28 03:00:58.179022+00
descriptionA Rust client library for the Mindat API - access mineralogical data including geomaterials, localities, and IMA minerals
homepage
repositoryhttps://github.com/jtk18/mindat-rs
max_upload_size
id2008166
size334,417
Jason Kiniry (jtk18)

documentation

https://docs.rs/mindat-rs

README

mindat-rs

A Rust client library for the Mindat API.

Crates.io Documentation CI License: MIT

Mindat is the world's largest open database of minerals, rocks, meteorites, and the localities where they come from. This crate provides a type-safe, async interface to access mineralogical data.

Features

  • Full coverage of the Mindat API endpoints
  • Strongly-typed request builders and response models
  • Async/await support using tokio
  • Pagination helpers
  • Comprehensive error handling
  • Optional GUI application built with Tauri (supports desktop and mobile)

Installation

Add this to your Cargo.toml:

[dependencies]
mindat-rs = "0.1"
tokio = { version = "1", features = ["full"] }

Quick Start

use mindat_rs::{MindatClient, GeomaterialsQuery, Result};

#[tokio::main]
async fn main() -> Result<()> {
    // Create a client with your API token
    let client = MindatClient::new("your-api-token");

    // Search for quartz
    let query = GeomaterialsQuery::new()
        .name("quartz")
        .ima_approved(true);

    let minerals = client.geomaterials(query).await?;

    for mineral in minerals.results {
        println!("{}: {:?}", mineral.id, mineral.name);
    }

    Ok(())
}

Authentication

Most API endpoints require authentication with a Mindat API token. You can obtain a token from your Mindat account settings.

Some endpoints (like minerals_ima) can be accessed without authentication:

use mindat_rs::{MindatClient, ImaMineralsQuery};

let client = MindatClient::anonymous();
let minerals = client.minerals_ima(ImaMineralsQuery::new()).await?;

Examples

Search for minerals by element composition

use mindat_rs::{MindatClient, GeomaterialsQuery};

let client = MindatClient::new("your-token");

// Find minerals containing copper and sulfur
let query = GeomaterialsQuery::new()
    .with_elements("Cu,S")
    .ima_approved(true)
    .page_size(50);

let minerals = client.geomaterials(query).await?;

Filter by physical properties

use mindat_rs::{MindatClient, GeomaterialsQuery, CrystalSystem};

let client = MindatClient::new("your-token");

// Find hard, dense minerals in the cubic system
let query = GeomaterialsQuery::new()
    .crystal_systems(vec![CrystalSystem::Isometric])
    .hardness_range(7.0, 10.0)
    .density_range(5.0, 20.0);

let minerals = client.geomaterials(query).await?;

Search localities

use mindat_rs::{MindatClient, LocalitiesQuery};

let client = MindatClient::new("your-token");

// Find gold localities in Brazil
let query = LocalitiesQuery::new()
    .country("Brazil")
    .with_elements("Au");

let localities = client.localities(query).await?;

Browse IMA minerals

use mindat_rs::{MindatClient, ImaMineralsQuery};

// IMA list doesn't require authentication
let client = MindatClient::anonymous();

let query = ImaMineralsQuery::new()
    .search("diamond")
    .page_size(10);

let minerals = client.minerals_ima(query).await?;

Pagination

use mindat_rs::{MindatClient, GeomaterialsQuery};

let client = MindatClient::new("your-token");

// Get first page
let query = GeomaterialsQuery::new().page(1).page_size(100);
let page1 = client.geomaterials(query).await?;

println!("Total minerals: {:?}", page1.count);

// Check if there are more pages
if page1.has_next() {
    let query = GeomaterialsQuery::new().page(2).page_size(100);
    let page2 = client.geomaterials(query).await?;
}

Custom client configuration

use mindat_rs::MindatClient;
use std::time::Duration;

let client = MindatClient::builder()
    .token("your-token")
    .timeout(Duration::from_secs(60))
    .build()?;

Available Endpoints

Endpoint Method Description
countries() GET List all countries
country(id) GET Get a specific country
geomaterials(query) GET Search minerals with filters
geomaterial(id) GET Get a specific geomaterial
geomaterial_varieties(id) GET Get varieties of a geomaterial
geomaterials_search(q, size) GET Quick search for geomaterials
localities(query) GET Search localities with filters
locality(id) GET Get a specific locality
locality_ages(page) GET List locality ages
locality_age(id) GET Get a specific age
locality_statuses(page) GET List locality statuses
locality_status(id) GET Get a specific status
locality_types(page) GET List locality types
locality_type(id) GET Get a specific type
minerals_ima(query) GET List IMA-approved minerals
mineral_ima(id) GET Get a specific IMA mineral
dana8_groups() GET Dana 8th ed. classification groups
dana8_subgroups() GET Dana 8th ed. classification subgroups
dana8(id) GET Get a specific Dana classification
strunz10_classes() GET Nickel-Strunz 10th ed. classes
strunz10_subclasses() GET Nickel-Strunz 10th ed. subclasses
strunz10_families() GET Nickel-Strunz 10th ed. families
strunz10(id) GET Get a specific Strunz classification

Error Handling

The library provides detailed error types:

use mindat_rs::{MindatClient, MindatError, GeomaterialsQuery};

let client = MindatClient::new("your-token");
let query = GeomaterialsQuery::new().name("quartz");

match client.geomaterials(query).await {
    Ok(minerals) => println!("Found {} minerals", minerals.results.len()),
    Err(MindatError::AuthenticationRequired) => {
        eprintln!("Invalid or missing API token");
    }
    Err(MindatError::RateLimited) => {
        eprintln!("Too many requests, please wait");
    }
    Err(MindatError::NotFound(msg)) => {
        eprintln!("Resource not found: {}", msg);
    }
    Err(e) => eprintln!("Error: {}", e),
}

GUI Application (Optional)

This crate includes an optional GUI application built with Tauri for testing and exploring the Mindat API. The GUI provides a user-friendly interface to:

  • Search minerals by name, elements, or properties
  • Browse IMA-approved minerals (no authentication required)
  • Explore localities and countries
  • View classification systems (Dana-8, Strunz-10)
  • Get detailed mineral information

Prerequisites

Linux:

# Ubuntu/Debian
sudo apt update
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file \
  libssl-dev libayatana-appindicator3-dev librsvg2-dev

# Fedora
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file \
  libappindicator-gtk3-devel librsvg2-devel

macOS:

xcode-select --install

Windows:

Building the GUI

# From the repository root
cd gui/src-tauri
cargo build --release

# Or run in development mode
cargo run

Running the GUI

After building, the executable will be at:

  • Linux/macOS: target/release/mindat-gui
  • Windows: target\release\mindat-gui.exe

Using the GUI

  1. Launch the application
  2. Enter your Mindat API token (from mindat.org) and click "Connect"
  3. Use the sidebar to select different API endpoints
  4. The "IMA Minerals" endpoint works without authentication

Mobile Support (iOS/Android)

The GUI is built with Tauri 2.0, which supports mobile platforms. To build for iOS:

# Install Tauri CLI
cargo install tauri-cli

# Initialize iOS (requires Xcode)
cd gui/src-tauri
cargo tauri ios init

# Build for iOS
cargo tauri ios build

For Android:

# Initialize Android (requires Android Studio)
cargo tauri android init

# Build for Android
cargo tauri android build

See the Tauri Mobile Guide for detailed setup instructions.

Related Projects

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Acknowledgments

  • Mindat.org for providing the mineralogical database and API
  • The OpenMindat R package for implementation reference
Commit count: 0

cargo fmt