pub mod create;
pub mod delete;
pub mod home_set;
pub mod list;
pub mod update;
use alloc::{format, string::String, vec::Vec};
use serde::{Deserialize, Serialize};
use crate::rfc4918::{
DISPLAYNAME, GETCTAG, Namespace, Property, RESOURCETYPE, SYNC_TOKEN, escape_text,
report_query_body,
};
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
pub struct Addressbook {
pub id: String,
pub display_name: Option<String>,
pub description: Option<String>,
pub color: Option<String>,
pub ctag: Option<String>,
pub sync_token: Option<String>,
}
pub const CARDDAV: Namespace = Namespace {
uri: "urn:ietf:params:xml:ns:carddav",
prefix: "C",
};
pub const INFIT: Namespace = Namespace {
uri: "http://inf-it.com/ns/ab/",
prefix: "I",
};
pub const ADDRESSBOOK: Property = Property {
ns: CARDDAV,
local: "addressbook",
};
pub const ADDRESSBOOK_HOME_SET: Property = Property {
ns: CARDDAV,
local: "addressbook-home-set",
};
pub const ADDRESSBOOK_DESCRIPTION: Property = Property {
ns: CARDDAV,
local: "addressbook-description",
};
pub const ADDRESS_DATA: Property = Property {
ns: CARDDAV,
local: "address-data",
};
pub const ADDRESSBOOK_COLOR: Property = Property {
ns: INFIT,
local: "addressbook-color",
};
pub const ADDRESSBOOK_QUERY: Property = Property {
ns: CARDDAV,
local: "addressbook-query",
};
pub const ADDRESSBOOK_MULTIGET: Property = Property {
ns: CARDDAV,
local: "addressbook-multiget",
};
pub const LIST_PROPS: &[Property] = &[
RESOURCETYPE,
DISPLAYNAME,
ADDRESSBOOK_DESCRIPTION,
ADDRESSBOOK_COLOR,
GETCTAG,
SYNC_TOKEN,
];
pub fn join_path(home: &str, id: &str) -> String {
let home = home.trim_end_matches('/');
let id = id.trim_start_matches('/');
format!("{home}/{id}/")
}
pub fn property_set(addressbook: &Addressbook) -> Vec<(Property, &str)> {
let mut set = Vec::new();
if let Some(name) = &addressbook.display_name {
set.push((DISPLAYNAME, name.as_str()));
}
if let Some(color) = &addressbook.color {
set.push((ADDRESSBOOK_COLOR, color.as_str()));
}
if let Some(description) = &addressbook.description {
set.push((ADDRESSBOOK_DESCRIPTION, description.as_str()));
}
set
}
pub fn addressbook_query_body(props: &[Property]) -> Vec<u8> {
let filter = "<C:filter test=\"allof\"></C:filter>";
report_query_body(ADDRESSBOOK_QUERY, &[CARDDAV], props, filter)
}
pub fn addressbook_multiget_body(hrefs: &[String], props: &[Property]) -> Vec<u8> {
let mut fragment = String::new();
for href in hrefs {
fragment.push_str(&format!("<D:href>{}</D:href>", escape_text(href)));
}
report_query_body(ADDRESSBOOK_MULTIGET, &[CARDDAV], props, &fragment)
}