car-integrations 0.6.0

OS-native account-bound integrations (Calendar, Contacts, Mail) for CAR
Documentation
//! Contacts capability — enumerate containers, query contacts.

use serde::{Deserialize, Serialize};

use super::{Availability, IntegrationError};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Container {
    pub id: String,
    pub name: String,
    /// Source label (account / provider) when available.
    pub source: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Contact {
    pub id: String,
    pub container_id: Option<String>,
    pub display_name: String,
    #[serde(default)]
    pub emails: Vec<String>,
    #[serde(default)]
    pub phone_numbers: Vec<String>,
    pub organization: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContainerListing {
    #[serde(flatten)]
    pub availability: Availability,
    pub containers: Vec<Container>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContactListing {
    #[serde(flatten)]
    pub availability: Availability,
    pub contacts: Vec<Contact>,
    /// Total match count, which may be larger than `contacts.len()` when
    /// the backend paginates.
    pub total: usize,
}

pub fn list_containers() -> Result<ContainerListing, IntegrationError> {
    Ok(ContainerListing {
        availability: current_backend_pending(),
        containers: vec![],
    })
}

/// Query contacts with a free-text `query` (name, email, phone substring).
/// When `container_ids` is empty, searches all accessible containers.
pub fn list_contacts(
    _query: &str,
    _container_ids: &[String],
    _limit: usize,
) -> Result<ContactListing, IntegrationError> {
    Ok(ContactListing {
        availability: current_backend_pending(),
        contacts: vec![],
        total: 0,
    })
}

fn current_backend_pending() -> Availability {
    #[cfg(target_os = "macos")]
    {
        Availability::pending(
            "contacts_framework",
            "Contacts.framework backend not yet wired. API shape is \
             stable; downstream apps can code against it now.",
        )
    }
    #[cfg(target_os = "windows")]
    {
        Availability::pending(
            "windows_contacts",
            "Windows Contacts API + MS Graph backends not yet wired. \
             API shape is stable; downstream apps can code against it now.",
        )
    }
    #[cfg(target_os = "linux")]
    {
        Availability::pending(
            "eds",
            "Evolution Data Server + CardDAV backends not yet wired. \
             API shape is stable; downstream apps can code against it now.",
        )
    }
    #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
    {
        Availability::pending("none", "Unsupported OS — no contacts backend modeled.")
    }
}