use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[allow(non_snake_case)] pub struct User {
pub id: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub username: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub color: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub profilePicture: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub initials: Option<String>,
}
impl User {
pub fn new(id: u32) -> Self {
Self {
id,
username: None,
email: None,
color: None,
profilePicture: None,
initials: None,
}
}
pub fn with_username(id: u32, username: impl Into<String>) -> Self {
Self {
id,
username: Some(username.into()),
email: None,
color: None,
profilePicture: None,
initials: None,
}
}
pub fn with_email(id: u32, username: impl Into<String>, email: impl Into<String>) -> Self {
Self {
id,
username: Some(username.into()),
email: Some(email.into()),
color: None,
profilePicture: None,
initials: None,
}
}
}
pub type Assignee = User;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AssigneeList {
pub add: Vec<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rem: Option<Vec<u32>>,
}
impl AssigneeList {
pub fn new() -> Self {
Self {
add: Vec::new(),
rem: None,
}
}
pub fn add(user_ids: Vec<u32>) -> Self {
Self {
add: user_ids,
rem: None,
}
}
pub fn add_and_remove(add: Vec<u32>, rem: Vec<u32>) -> Self {
Self {
add,
rem: Some(rem),
}
}
pub fn add_assignee(&mut self, user_id: u32) {
if !self.add.contains(&user_id) {
self.add.push(user_id);
}
}
pub fn remove_assignee(&mut self, user_id: u32) {
if let Some(ref mut rem) = self.rem {
if !rem.contains(&user_id) {
rem.push(user_id);
}
} else {
self.rem = Some(vec![user_id]);
}
}
pub fn is_empty(&self) -> bool {
self.add.is_empty() && self.rem.as_ref().map_or(true, |r| r.is_empty())
}
}
impl Default for AssigneeList {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_user_new() {
let user = User::new(123);
assert_eq!(user.id, 123);
assert!(user.username.is_none());
}
#[test]
fn test_user_with_username() {
let user = User::with_username(456, "john");
assert_eq!(user.id, 456);
assert_eq!(user.username, Some("john".to_string()));
}
#[test]
fn test_user_with_email() {
let user = User::with_email(789, "jane", "jane@example.com");
assert_eq!(user.id, 789);
assert_eq!(user.username, Some("jane".to_string()));
assert_eq!(user.email, Some("jane@example.com".to_string()));
}
#[test]
fn test_assignee_list_new() {
let list = AssigneeList::new();
assert!(list.add.is_empty());
assert!(list.rem.is_none());
assert!(list.is_empty());
}
#[test]
fn test_assignee_list_add() {
let list = AssigneeList::add(vec![1, 2, 3]);
assert_eq!(list.add, vec![1, 2, 3]);
assert!(list.rem.is_none());
assert!(!list.is_empty());
}
#[test]
fn test_assignee_list_add_assignee() {
let mut list = AssigneeList::new();
list.add_assignee(100);
list.add_assignee(200);
list.add_assignee(100); assert_eq!(list.add, vec![100, 200]);
}
#[test]
fn test_assignee_list_remove_assignee() {
let mut list = AssigneeList::add(vec![1, 2, 3]);
list.remove_assignee(2);
list.remove_assignee(3);
assert_eq!(list.rem, Some(vec![2, 3]));
}
}