use alloc::{borrow::ToOwned, format, string::String, vec, vec::Vec};
use secrecy::SecretString;
use serde::Serialize;
use thiserror::Error;
use crate::{
coroutine::*,
jmap_try,
rfc8620::{JMAP_CORE_CAPABILITY, get::*, session::JmapSession},
rfc9610::{JMAP_CONTACTS_CAPABILITY, address_book::JmapAddressBook},
};
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum JmapAddressBookProperty {
Id,
Name,
Description,
SortOrder,
IsDefault,
IsSubscribed,
ShareWith,
MyRights,
}
#[derive(Debug, Error)]
pub enum JmapAddressBookGetError {
#[error("JMAP AddressBook/get failed: {0}")]
Get(#[from] JmapGetError),
}
#[derive(Clone, Debug, Default)]
pub struct JmapAddressBookGetOptions {
pub ids: Option<Vec<String>>,
pub properties: Option<Vec<JmapAddressBookProperty>>,
}
#[derive(Clone, Debug)]
pub struct JmapAddressBookGetOutput {
pub address_books: Vec<JmapAddressBook>,
pub not_found: Vec<String>,
pub new_state: String,
pub keep_alive: bool,
}
pub struct JmapAddressBookGet {
state: State,
}
impl JmapAddressBookGet {
pub fn new(
session: &JmapSession,
http_auth: &SecretString,
opts: JmapAddressBookGetOptions,
) -> Result<Self, JmapAddressBookGetError> {
let account_id = session
.primary_accounts
.get(JMAP_CONTACTS_CAPABILITY)
.cloned()
.unwrap_or_default();
let api_url = &session.api_url;
let props = opts.properties.map(|ps| {
ps.iter()
.map(|p| {
serde_json::to_value(p)
.ok()
.and_then(|v| v.as_str().map(str::to_owned))
.unwrap_or_else(|| format!("{p:?}"))
})
.collect()
});
Ok(Self {
state: State::Get(JmapGet::new(
account_id,
http_auth,
api_url,
"AddressBook/get",
vec![JMAP_CORE_CAPABILITY.into(), JMAP_CONTACTS_CAPABILITY.into()],
JmapGetOptions {
ids: opts.ids,
properties: props,
},
)?),
})
}
}
impl JmapCoroutine for JmapAddressBookGet {
type Yield = JmapYield;
type Return = Result<JmapAddressBookGetOutput, JmapAddressBookGetError>;
fn resume(&mut self, arg: Option<&[u8]>) -> JmapCoroutineState<Self::Yield, Self::Return> {
match &mut self.state {
State::Get(get) => {
let JmapGetOutput {
list,
not_found,
state,
keep_alive,
} = jmap_try!(get, arg);
JmapCoroutineState::Complete(Ok(JmapAddressBookGetOutput {
address_books: list,
not_found,
new_state: state,
keep_alive,
}))
}
}
}
}
enum State {
Get(JmapGet<JmapAddressBook>),
}