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 PageSlug(String);

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PageRef {
    pub slug: PageSlug,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Visibility {
    Public,
    Draft,
    Unlisted,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PageDraft {
    pub slug: PageSlug,
    pub title: String,
    pub body: String,
    pub visibility: Visibility,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct PageUpdate {
    pub title: Option<String>,
    pub body: Option<String>,
    pub visibility: Option<Visibility>,
}

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

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PageDocument {
    pub slug: PageSlug,
    pub title: Option<String>,
    pub body: Option<String>,
    pub visibility: Option<Visibility>,
    pub raw: serde_json::Value,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PageDeleteResult {
    pub deleted: bool,
    pub raw: serde_json::Value,
}

impl PageSlug {
    pub fn parse(input: impl AsRef<str>) -> crate::ImResult<Self> {
        let value = input.as_ref().trim();
        if value.is_empty() {
            return Err(crate::ImError::invalid_input(
                Some("slug".to_string()),
                "slug is required",
            ));
        }
        Ok(Self(value.to_string()))
    }

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

impl PageRef {
    pub fn new(slug: PageSlug) -> Self {
        Self { slug }
    }
}

impl Visibility {
    pub fn parse(input: impl AsRef<str>) -> crate::ImResult<Self> {
        match input.as_ref().trim().to_ascii_lowercase().as_str() {
            "" | "public" => Ok(Self::Public),
            "draft" => Ok(Self::Draft),
            "unlisted" => Ok(Self::Unlisted),
            _ => Err(crate::ImError::invalid_input(
                Some("visibility".to_string()),
                "visibility must be one of public, draft, or unlisted",
            )),
        }
    }

    pub fn as_str(self) -> &'static str {
        match self {
            Self::Public => "public",
            Self::Draft => "draft",
            Self::Unlisted => "unlisted",
        }
    }
}

impl PageDraft {
    pub fn new(
        slug: PageSlug,
        title: impl Into<String>,
        body: impl Into<String>,
        visibility: Visibility,
    ) -> crate::ImResult<Self> {
        let title = title.into();
        if title.trim().is_empty() {
            return Err(crate::ImError::invalid_input(
                Some("title".to_string()),
                "title is required",
            ));
        }
        Ok(Self {
            slug,
            title,
            body: body.into(),
            visibility,
        })
    }
}

impl Default for ContentPageQuery {
    fn default() -> Self {
        Self {
            limit: crate::ids::PageLimit(50),
            cursor: None,
        }
    }
}