use std::fmt::Display;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum ShareType {
#[default]
User,
Group,
Federation,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
#[serde(try_from = "String", into = "String")]
pub struct OcmAddress {
address: String,
separator_index: usize
}
impl OcmAddress {
pub fn get_identifier(&self) -> &str {
self.address.split_at(self.separator_index).0
}
pub fn get_server_url(&self) -> &str {
self.address.split_at(self.separator_index+1).1
}
}
impl TryFrom<&str> for OcmAddress {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.to_string().try_into()
}
}
impl TryFrom<String> for OcmAddress {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
if value.is_empty() {
Err("OCM Address may not be empty")?
}
let separator_index = value.rfind('@')
.ok_or("Missing '@' separator in OCM Address")?;
if separator_index == 0 {
Err("UserId before the '@' character in OCM Address may not be empty")?
}
if separator_index == value.len() - 1 {
Err("OCM Server FQDN after the '@' character in OCM Address may not be empty")?
}
let host = value.split_at(separator_index+1).1;
if host.contains('/') {
Err("OCM Address may not contain a path or scheme")?
};
Ok(Self {
address: value,
separator_index
})
}
}
impl Display for OcmAddress {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.address)?;
Ok(())
}
}
impl From<OcmAddress> for String {
fn from(val: OcmAddress) -> Self {
val.address
}
}
impl AsRef<str> for OcmAddress {
fn as_ref(&self) -> &str {
&self.address
}
}
#[cfg(test)]
mod test {
use super::OcmAddress;
#[test]
fn invalid_ocm_addresses() {
OcmAddress::try_from("").expect_err("OCM Address may not be empty");
OcmAddress::try_from("user@https://example.org").expect_err("Scheme is not allowed in server address part");
OcmAddress::try_from("user@example.org/subfolder").expect_err("Scheme is not allowed in server address part");
OcmAddress::try_from("@example.org").expect_err("Empty user Id must be rejected");
OcmAddress::try_from("user@").expect_err("Empty Server FQDN must be rejected");
OcmAddress::try_from("@").expect_err("Empty User Id and Empty Server FQDN must be rejected");
}
#[test]
fn valid_ocm_addresses() {
let address = OcmAddress::try_from("asdf@user@example.org").expect("asdf@user@example.org should be accepted");
assert_eq!(("asdf@user", "example.org"), (address.get_identifier(), address.get_server_url()));
let address = OcmAddress::try_from("🤡asdf@user@example.org:8080").expect("🤡asdf@user@example.org:8080 should be accepted");
assert_eq!(("🤡asdf@user", "example.org:8080"), (address.get_identifier(), address.get_server_url()));
let address = OcmAddress::try_from("asdf@user@127.0.0.1").expect("asdf@user@127.0.0.1 should be accepted");
assert_eq!(("asdf@user", "127.0.0.1"), (address.get_identifier(), address.get_server_url()));
let address = OcmAddress::try_from("asdf@user@[fe80::cc7f:2f7d:80f6:3876%en0]").expect("asdf@user@[fe80::cc7f:2f7d:80f6:3876%en0] should be accepted");
assert_eq!(("asdf@user", "[fe80::cc7f:2f7d:80f6:3876%en0]"), (address.get_identifier(), address.get_server_url()));
}
}