use crate::time::date::Date;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ExerciseType {
American,
Bermudan,
European,
}
pub trait Exercise {
fn exercise_type(&self) -> ExerciseType;
fn dates(&self) -> &[Date];
fn last_date(&self) -> Date {
*self
.dates()
.last()
.expect("no exercise date given (implementors guarantee at least one)")
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct EuropeanExercise {
dates: [Date; 1],
}
impl EuropeanExercise {
pub fn new(date: Date) -> EuropeanExercise {
EuropeanExercise { dates: [date] }
}
}
impl Exercise for EuropeanExercise {
fn exercise_type(&self) -> ExerciseType {
ExerciseType::European
}
fn dates(&self) -> &[Date] {
&self.dates
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::time::date::Month;
#[test]
fn european_exercise_holds_the_single_expiry() {
let expiry = Date::new(17, Month::May, 2027);
let exercise = EuropeanExercise::new(expiry);
assert_eq!(exercise.exercise_type(), ExerciseType::European);
assert_eq!(exercise.dates(), &[expiry]);
assert_eq!(exercise.last_date(), expiry);
}
#[test]
fn usable_as_trait_object() {
let expiry = Date::new(31, Month::December, 2030);
let exercise: &dyn Exercise = &EuropeanExercise::new(expiry);
assert_eq!(exercise.last_date(), expiry);
assert_eq!(exercise.dates().len(), 1);
}
}