use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum UserIdType {
#[serde(rename = "open_id")]
OpenId,
#[serde(rename = "user_id")]
UserId,
#[serde(rename = "union_id")]
UnionId,
}
impl UserIdType {
pub fn as_str(&self) -> &str {
match self {
UserIdType::OpenId => "open_id",
UserIdType::UserId => "user_id",
UserIdType::UnionId => "union_id",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Task {
#[serde(skip_serializing_if = "Option::is_none")]
pub guid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub due: Option<TaskDue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start: Option<TaskStart>,
#[serde(skip_serializing_if = "Option::is_none")]
pub completed_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub members: Option<Vec<TaskMember>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub repeat_rule: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub custom_complete: Option<TaskCustomComplete>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub workflow_state: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskDue {
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_all_day: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskStart {
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_all_day: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskMember {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub role: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskCustomComplete {
#[serde(skip_serializing_if = "Option::is_none")]
pub mode: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub complete_setting: Option<TaskCompleteSetting>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskCompleteSetting {
#[serde(skip_serializing_if = "Option::is_none")]
pub subtask_count: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Tasklist {
#[serde(skip_serializing_if = "Option::is_none")]
pub guid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub creator: Option<TaskMember>,
#[serde(skip_serializing_if = "Option::is_none")]
pub owner: Option<TaskMember>,
#[serde(skip_serializing_if = "Option::is_none")]
pub members: Option<Vec<TaskMember>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Comment {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub creator: Option<TaskMember>,
#[serde(skip_serializing_if = "Option::is_none")]
pub replies: Option<Vec<Comment>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Attachment {
#[serde(skip_serializing_if = "Option::is_none")]
pub guid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub uploader: Option<TaskMember>,
#[serde(skip_serializing_if = "Option::is_none")]
pub uploaded_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Section {
#[serde(skip_serializing_if = "Option::is_none")]
pub guid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_default: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomField {
#[serde(skip_serializing_if = "Option::is_none")]
pub guid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub setting: Option<CustomFieldSetting>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomFieldSetting {
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<Vec<CustomFieldOption>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomFieldOption {
#[serde(skip_serializing_if = "Option::is_none")]
pub guid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub color_index: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Reminder {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub relative_fire_minute: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Dependency {
#[serde(skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub task_guid: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ActivitySubscription {
#[serde(skip_serializing_if = "Option::is_none")]
pub guid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscribers: Option<Vec<TaskMember>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub include_completed: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
}
#[cfg(test)]
#[allow(unused_variables, unused_unsafe)]
mod tests {
use super::*;
use serde_json;
#[test]
fn test_user_id_type_as_str() {
assert_eq!(UserIdType::OpenId.as_str(), "open_id");
assert_eq!(UserIdType::UserId.as_str(), "user_id");
assert_eq!(UserIdType::UnionId.as_str(), "union_id");
}
#[test]
fn test_user_id_type_serialization() {
let open_id = UserIdType::OpenId;
let serialized = serde_json::to_string(&open_id).unwrap();
assert_eq!(serialized, "\"open_id\"");
let user_id = UserIdType::UserId;
let serialized = serde_json::to_string(&user_id).unwrap();
assert_eq!(serialized, "\"user_id\"");
let union_id = UserIdType::UnionId;
let serialized = serde_json::to_string(&union_id).unwrap();
assert_eq!(serialized, "\"union_id\"");
}
#[test]
fn test_user_id_type_deserialization() {
let deserialized: UserIdType = serde_json::from_str("\"open_id\"").unwrap();
assert!(matches!(deserialized, UserIdType::OpenId));
let deserialized: UserIdType = serde_json::from_str("\"user_id\"").unwrap();
assert!(matches!(deserialized, UserIdType::UserId));
let deserialized: UserIdType = serde_json::from_str("\"union_id\"").unwrap();
assert!(matches!(deserialized, UserIdType::UnionId));
}
#[test]
fn test_task_serialization() {
let task = Task {
guid: Some("task123".to_string()),
summary: Some("Test Task".to_string()),
description: Some("This is a test task".to_string()),
due: Some(TaskDue {
timestamp: Some("2023-12-31T23:59:59Z".to_string()),
is_all_day: Some(false),
}),
start: Some(TaskStart {
timestamp: Some("2023-01-01T00:00:00Z".to_string()),
is_all_day: Some(false),
}),
completed_at: None,
members: Some(vec![TaskMember {
id: Some("user123".to_string()),
type_: Some("user".to_string()),
role: Some("assignee".to_string()),
}]),
repeat_rule: None,
custom_complete: None,
created_at: Some("2023-01-01T00:00:00Z".to_string()),
updated_at: Some("2023-01-01T01:00:00Z".to_string()),
status: Some("pending".to_string()),
workflow_state: Some("active".to_string()),
source: Some(1),
url: Some("https://example.com/task/123".to_string()),
};
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: Task = serde_json::from_str(&serialized).unwrap();
assert_eq!(task.guid, deserialized.guid);
assert_eq!(task.summary, deserialized.summary);
assert_eq!(task.description, deserialized.description);
assert_eq!(task.status, deserialized.status);
}
#[test]
fn test_task_due_serialization() {
let due = TaskDue {
timestamp: Some("2023-12-31T23:59:59Z".to_string()),
is_all_day: Some(true),
};
let serialized = serde_json::to_string(&due).unwrap();
let deserialized: TaskDue = serde_json::from_str(&serialized).unwrap();
assert_eq!(due.timestamp, deserialized.timestamp);
assert_eq!(due.is_all_day, deserialized.is_all_day);
}
#[test]
fn test_task_member_serialization() {
let member = TaskMember {
id: Some("user123".to_string()),
type_: Some("user".to_string()),
role: Some("assignee".to_string()),
};
let serialized = serde_json::to_string(&member).unwrap();
let deserialized: TaskMember = serde_json::from_str(&serialized).unwrap();
assert_eq!(member.id, deserialized.id);
assert_eq!(member.type_, deserialized.type_);
assert_eq!(member.role, deserialized.role);
}
#[test]
fn test_activity_subscription_serialization() {
let subscription = ActivitySubscription {
guid: Some("sub123".to_string()),
name: Some("Task Updates".to_string()),
subscribers: Some(vec![TaskMember {
id: Some("user123".to_string()),
type_: Some("user".to_string()),
role: Some("subscriber".to_string()),
}]),
include_completed: Some(true),
created_at: Some("2023-01-01T00:00:00Z".to_string()),
updated_at: Some("2023-01-01T01:00:00Z".to_string()),
};
let serialized = serde_json::to_string(&subscription).unwrap();
let deserialized: ActivitySubscription = serde_json::from_str(&serialized).unwrap();
assert_eq!(subscription.guid, deserialized.guid);
assert_eq!(subscription.name, deserialized.name);
assert_eq!(
subscription.include_completed,
deserialized.include_completed
);
}
#[test]
fn test_models_with_none_values() {
let task = Task {
guid: None,
summary: None,
description: None,
due: None,
start: None,
completed_at: None,
members: None,
repeat_rule: None,
custom_complete: None,
created_at: None,
updated_at: None,
status: None,
workflow_state: None,
source: None,
url: None,
};
let serialized = serde_json::to_string(&task).unwrap();
assert_eq!(serialized, "{}");
let deserialized: Task = serde_json::from_str("{}").unwrap();
assert_eq!(deserialized.guid, None);
assert_eq!(deserialized.summary, None);
}
#[test]
fn test_debug_trait_for_models() {
let task = Task {
guid: Some("task123".to_string()),
summary: Some("Test".to_string()),
description: None,
due: None,
start: None,
completed_at: None,
members: None,
repeat_rule: None,
custom_complete: None,
created_at: None,
updated_at: None,
status: None,
workflow_state: None,
source: None,
url: None,
};
let debug_output = format!("{:?}", task);
assert!(debug_output.contains("Task"));
assert!(debug_output.contains("task123"));
}
#[test]
fn test_clone_trait_for_models() {
let original_member = TaskMember {
id: Some("user123".to_string()),
type_: Some("user".to_string()),
role: Some("assignee".to_string()),
};
let cloned_member = original_member.clone();
assert_eq!(original_member.id, cloned_member.id);
assert_eq!(original_member.type_, cloned_member.type_);
assert_eq!(original_member.role, cloned_member.role);
}
}