use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TimeSlot {
pub emails: Vec<String>,
pub start_time: i64,
pub end_time: i64,
}
impl TimeSlot {
pub fn new(emails: Vec<String>, start_time: i64, end_time: i64) -> Self {
Self {
emails,
start_time,
end_time,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AvailabilityResponse {
pub time_slots: Vec<TimeSlot>,
}
impl AvailabilityResponse {
pub fn new(time_slots: Vec<TimeSlot>) -> Self {
Self { time_slots }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AvailabilityRequest {
pub emails: Vec<String>,
pub duration_minutes: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub interval_minutes: Option<u32>,
pub start_time: i64,
pub end_time: i64,
}
impl AvailabilityRequest {
pub fn builder() -> AvailabilityRequestBuilder {
AvailabilityRequestBuilder {
emails: Vec::new(),
duration_minutes: None,
interval_minutes: None,
start_time: None,
end_time: None,
}
}
pub fn new(emails: Vec<String>, duration_minutes: u32, start_time: i64, end_time: i64) -> Self {
Self {
emails,
duration_minutes,
interval_minutes: None,
start_time,
end_time,
}
}
}
#[derive(Debug, Clone)]
pub struct AvailabilityRequestBuilder {
emails: Vec<String>,
duration_minutes: Option<u32>,
interval_minutes: Option<u32>,
start_time: Option<i64>,
end_time: Option<i64>,
}
impl AvailabilityRequestBuilder {
pub fn email(mut self, email: impl Into<String>) -> Self {
self.emails.push(email.into());
self
}
pub fn emails(mut self, emails: Vec<String>) -> Self {
self.emails.extend(emails);
self
}
pub fn duration_minutes(mut self, duration: u32) -> Self {
self.duration_minutes = Some(duration);
self
}
pub fn interval_minutes(mut self, interval: u32) -> Self {
self.interval_minutes = Some(interval);
self
}
pub fn start_time(mut self, start_time: i64) -> Self {
self.start_time = Some(start_time);
self
}
pub fn end_time(mut self, end_time: i64) -> Self {
self.end_time = Some(end_time);
self
}
pub fn build(self) -> AvailabilityRequest {
AvailabilityRequest {
emails: if self.emails.is_empty() {
panic!("At least one email address is required")
} else {
self.emails
},
duration_minutes: self.duration_minutes.expect("duration_minutes is required"),
interval_minutes: self.interval_minutes,
start_time: self.start_time.expect("start_time is required"),
end_time: self.end_time.expect("end_time is required"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_time_slot_creation() {
let slot = TimeSlot::new(vec!["user@example.com".to_string()], 1234567890, 1234571490);
assert_eq!(slot.emails.len(), 1);
assert_eq!(slot.emails[0], "user@example.com");
assert_eq!(slot.start_time, 1234567890);
assert_eq!(slot.end_time, 1234571490);
}
#[test]
fn test_time_slot_serialization() {
let slot = TimeSlot::new(vec!["user@example.com".to_string()], 1234567890, 1234571490);
let json = serde_json::to_string(&slot).unwrap();
assert!(json.contains("user@example.com"));
assert!(json.contains("1234567890"));
assert!(json.contains("1234571490"));
let deserialized: TimeSlot = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, slot);
}
#[test]
fn test_availability_response_creation() {
let slots = vec![TimeSlot::new(
vec!["user@example.com".to_string()],
1234567890,
1234571490,
)];
let response = AvailabilityResponse::new(slots.clone());
assert_eq!(response.time_slots.len(), 1);
assert_eq!(response.time_slots[0], slots[0]);
}
#[test]
fn test_availability_response_serialization() {
let response = AvailabilityResponse::new(vec![TimeSlot::new(
vec!["user@example.com".to_string()],
1234567890,
1234571490,
)]);
let json = serde_json::to_string(&response).unwrap();
assert!(json.contains("user@example.com"));
let deserialized: AvailabilityResponse = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, response);
}
#[test]
fn test_availability_request_new() {
let request = AvailabilityRequest::new(
vec!["user@example.com".to_string()],
30,
1234567890,
1234654290,
);
assert_eq!(request.emails.len(), 1);
assert_eq!(request.emails[0], "user@example.com");
assert_eq!(request.duration_minutes, 30);
assert_eq!(request.start_time, 1234567890);
assert_eq!(request.end_time, 1234654290);
assert_eq!(request.interval_minutes, None);
}
#[test]
fn test_availability_request_builder_single_email() {
let request = AvailabilityRequest::builder()
.email("user@example.com")
.duration_minutes(30)
.start_time(1234567890)
.end_time(1234654290)
.build();
assert_eq!(request.emails.len(), 1);
assert_eq!(request.emails[0], "user@example.com");
assert_eq!(request.duration_minutes, 30);
}
#[test]
fn test_availability_request_builder_multiple_emails() {
let request = AvailabilityRequest::builder()
.email("user1@example.com")
.email("user2@example.com")
.duration_minutes(45)
.interval_minutes(15)
.start_time(1234567890)
.end_time(1234654290)
.build();
assert_eq!(request.emails.len(), 2);
assert_eq!(request.duration_minutes, 45);
assert_eq!(request.interval_minutes, Some(15));
}
#[test]
fn test_availability_request_builder_with_emails_vec() {
let emails = vec![
"user1@example.com".to_string(),
"user2@example.com".to_string(),
];
let request = AvailabilityRequest::builder()
.emails(emails)
.duration_minutes(60)
.start_time(1234567890)
.end_time(1234654290)
.build();
assert_eq!(request.emails.len(), 2);
assert_eq!(request.duration_minutes, 60);
}
#[test]
#[should_panic(expected = "At least one email address is required")]
fn test_availability_request_builder_no_emails() {
AvailabilityRequest::builder()
.duration_minutes(30)
.start_time(1234567890)
.end_time(1234654290)
.build();
}
#[test]
#[should_panic(expected = "duration_minutes is required")]
fn test_availability_request_builder_no_duration() {
AvailabilityRequest::builder()
.email("user@example.com")
.start_time(1234567890)
.end_time(1234654290)
.build();
}
#[test]
#[should_panic(expected = "start_time is required")]
fn test_availability_request_builder_no_start_time() {
AvailabilityRequest::builder()
.email("user@example.com")
.duration_minutes(30)
.end_time(1234654290)
.build();
}
#[test]
fn test_availability_request_serialization() {
let request = AvailabilityRequest::builder()
.email("user@example.com")
.duration_minutes(30)
.interval_minutes(15)
.start_time(1234567890)
.end_time(1234654290)
.build();
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("user@example.com"));
assert!(json.contains("30"));
assert!(json.contains("15"));
let deserialized: AvailabilityRequest = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, request);
}
#[test]
fn test_availability_request_serialization_no_interval() {
let request = AvailabilityRequest::new(
vec!["user@example.com".to_string()],
30,
1234567890,
1234654290,
);
let json = serde_json::to_string(&request).unwrap();
assert!(!json.contains("interval_minutes"));
let deserialized: AvailabilityRequest = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, request);
}
}