#[cfg(feature = "unstable_plan_operations")]
use std::sync::Arc;
#[cfg(feature = "unstable_plan_operations")]
use derive_more::{Display, From};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
use super::Meta;
use crate::{IntoOption, SkipListener};
#[serde_as]
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct Plan {
#[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
pub entries: Vec<PlanEntry>,
#[serde(rename = "_meta")]
pub meta: Option<Meta>,
}
impl Plan {
#[must_use]
pub fn new(entries: Vec<PlanEntry>) -> Self {
Self {
entries,
meta: None,
}
}
#[must_use]
pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
self.meta = meta.into_option();
self
}
}
#[cfg(feature = "unstable_plan_operations")]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
#[serde(transparent)]
#[from(Arc<str>, String, &'static str)]
#[non_exhaustive]
pub struct PlanId(pub Arc<str>);
#[cfg(feature = "unstable_plan_operations")]
impl PlanId {
#[must_use]
pub fn new(id: impl Into<Arc<str>>) -> Self {
Self(id.into())
}
}
#[cfg(feature = "unstable_plan_operations")]
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct PlanUpdate {
pub plan: PlanUpdateContent,
#[serde(rename = "_meta")]
pub meta: Option<Meta>,
}
#[cfg(feature = "unstable_plan_operations")]
impl PlanUpdate {
#[must_use]
pub fn new(plan: PlanUpdateContent) -> Self {
Self { plan, meta: None }
}
#[must_use]
pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
self.meta = meta.into_option();
self
}
}
#[cfg(feature = "unstable_plan_operations")]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(tag = "type", rename_all = "snake_case")]
#[schemars(extend("discriminator" = {"propertyName": "type"}))]
#[non_exhaustive]
pub enum PlanUpdateContent {
Items(PlanItems),
File(PlanFile),
Markdown(PlanMarkdown),
}
#[cfg(feature = "unstable_plan_operations")]
impl PlanUpdateContent {
#[must_use]
pub fn items(id: impl Into<PlanId>, entries: Vec<PlanEntry>) -> Self {
Self::Items(PlanItems::new(id, entries))
}
#[must_use]
pub fn file(id: impl Into<PlanId>, uri: impl Into<String>) -> Self {
Self::File(PlanFile::new(id, uri))
}
#[must_use]
pub fn markdown(id: impl Into<PlanId>, content: impl Into<String>) -> Self {
Self::Markdown(PlanMarkdown::new(id, content))
}
}
#[cfg(feature = "unstable_plan_operations")]
#[serde_as]
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct PlanItems {
pub id: PlanId,
#[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
pub entries: Vec<PlanEntry>,
#[serde(rename = "_meta")]
pub meta: Option<Meta>,
}
#[cfg(feature = "unstable_plan_operations")]
impl PlanItems {
#[must_use]
pub fn new(id: impl Into<PlanId>, entries: Vec<PlanEntry>) -> Self {
Self {
id: id.into(),
entries,
meta: None,
}
}
#[must_use]
pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
self.meta = meta.into_option();
self
}
}
#[cfg(feature = "unstable_plan_operations")]
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct PlanFile {
pub id: PlanId,
pub uri: String,
#[serde(rename = "_meta")]
pub meta: Option<Meta>,
}
#[cfg(feature = "unstable_plan_operations")]
impl PlanFile {
#[must_use]
pub fn new(id: impl Into<PlanId>, uri: impl Into<String>) -> Self {
Self {
id: id.into(),
uri: uri.into(),
meta: None,
}
}
#[must_use]
pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
self.meta = meta.into_option();
self
}
}
#[cfg(feature = "unstable_plan_operations")]
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct PlanMarkdown {
pub id: PlanId,
pub content: String,
#[serde(rename = "_meta")]
pub meta: Option<Meta>,
}
#[cfg(feature = "unstable_plan_operations")]
impl PlanMarkdown {
#[must_use]
pub fn new(id: impl Into<PlanId>, content: impl Into<String>) -> Self {
Self {
id: id.into(),
content: content.into(),
meta: None,
}
}
#[must_use]
pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
self.meta = meta.into_option();
self
}
}
#[cfg(feature = "unstable_plan_operations")]
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct PlanRemoved {
pub id: PlanId,
#[serde(rename = "_meta")]
pub meta: Option<Meta>,
}
#[cfg(feature = "unstable_plan_operations")]
impl PlanRemoved {
#[must_use]
pub fn new(id: impl Into<PlanId>) -> Self {
Self {
id: id.into(),
meta: None,
}
}
#[must_use]
pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
self.meta = meta.into_option();
self
}
}
#[cfg(feature = "unstable_plan_operations")]
#[skip_serializing_none]
#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct PlanCapabilities {
#[serde(rename = "_meta")]
pub meta: Option<Meta>,
}
#[cfg(feature = "unstable_plan_operations")]
impl PlanCapabilities {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
self.meta = meta.into_option();
self
}
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct PlanEntry {
pub content: String,
pub priority: PlanEntryPriority,
pub status: PlanEntryStatus,
#[serde(rename = "_meta")]
pub meta: Option<Meta>,
}
impl PlanEntry {
#[must_use]
pub fn new(
content: impl Into<String>,
priority: PlanEntryPriority,
status: PlanEntryStatus,
) -> Self {
Self {
content: content.into(),
priority,
status,
meta: None,
}
}
#[must_use]
pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
self.meta = meta.into_option();
self
}
}
#[derive(Deserialize, Serialize, JsonSchema, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum PlanEntryPriority {
High,
Medium,
Low,
}
#[derive(Deserialize, Serialize, JsonSchema, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum PlanEntryStatus {
Pending,
InProgress,
Completed,
}