im-core 0.1.0

Rust IM SDK for Awiki clients built on Agent Network Protocol (ANP)
Documentation
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SiteDomain(String);

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SiteRootDraft {
    pub domain: SiteDomain,
    pub body: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SiteRootDocument {
    pub domain: SiteDomain,
    pub body: Option<String>,
    pub raw: serde_json::Value,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SitePageRef {
    pub domain: SiteDomain,
    pub slug: crate::content::PageSlug,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SitePageQuery {
    pub domain: SiteDomain,
    pub limit: crate::ids::PageLimit,
    pub cursor: Option<crate::ids::Cursor>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SitePageDraft {
    pub domain: SiteDomain,
    pub slug: crate::content::PageSlug,
    pub body: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SitePageUpdate {
    pub body: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SitePageDocument {
    pub domain: SiteDomain,
    pub slug: crate::content::PageSlug,
    pub body: Option<String>,
    pub raw: serde_json::Value,
}

impl SiteDomain {
    pub fn parse(input: impl AsRef<str>) -> crate::ImResult<Self> {
        let normalized = input
            .as_ref()
            .trim()
            .to_ascii_lowercase()
            .trim_end_matches('.')
            .to_string();
        if normalized.is_empty() {
            return Err(crate::ImError::invalid_input(
                Some("domain".to_string()),
                "did_domain is required",
            ));
        }
        if normalized.contains("://") {
            return Err(crate::ImError::invalid_input(
                Some("domain".to_string()),
                "did_domain must be a bare domain without a URL scheme",
            ));
        }
        if normalized.contains(['/', '?', '#']) {
            return Err(crate::ImError::invalid_input(
                Some("domain".to_string()),
                "did_domain must not include a path, query, or fragment",
            ));
        }
        if normalized.contains(':') {
            return Err(crate::ImError::invalid_input(
                Some("domain".to_string()),
                "did_domain must not include a port",
            ));
        }
        if normalized.chars().any(char::is_whitespace) {
            return Err(crate::ImError::invalid_input(
                Some("domain".to_string()),
                "did_domain must not contain whitespace",
            ));
        }
        if normalized.contains('@') || normalized.contains('%') {
            return Err(crate::ImError::invalid_input(
                Some("domain".to_string()),
                "did_domain must be a bare domain",
            ));
        }
        Ok(Self(normalized))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl SitePageRef {
    pub fn new(domain: SiteDomain, slug: crate::content::PageSlug) -> Self {
        Self { domain, slug }
    }
}

impl Default for SitePageQuery {
    fn default() -> Self {
        Self {
            domain: SiteDomain(String::new()),
            limit: crate::ids::PageLimit(50),
            cursor: None,
        }
    }
}