features, cleanup and bug fixes #26

Merged
ben merged 30 commits from ben/Jobboerse:main into main 2022-06-09 17:36:55 +02:00
Showing only changes of commit 4e78d960fa - Show all commits

impl Hash for JobOffer so a future edit dialog can detect concurrent modifications

Bennet Bleßmann 2022-05-30 21:52:16 +02:00 committed by Bennet Bleßmann
Signed by: ben
GPG key ID: 3BE1A1A3CBC3CF99

View file

@ -1,6 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::fmt::Formatter; use std::fmt::Formatter;
use std::hash::{Hash, Hasher};
use std::io::ErrorKind; use std::io::ErrorKind;
use std::net::IpAddr; use std::net::IpAddr;
use std::ops::{Add, Deref}; use std::ops::{Add, Deref};
@ -18,7 +19,7 @@ use rand::distributions::DistString;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use tokio::sync::{Mutex, RwLock, RwLockMappedWriteGuard, RwLockReadGuard, RwLockWriteGuard}; use tokio::sync::{Mutex, RwLock, RwLockMappedWriteGuard, RwLockReadGuard, RwLockWriteGuard};
use toml::value::Datetime; use toml::value::{Datetime, Offset};
use crate::auth::User; use crate::auth::User;
use crate::error::PresentationError; use crate::error::PresentationError;
@ -185,7 +186,7 @@ pub(crate) fn job_data<'i, I: Iterator<Item = (&'i str, &'i JobOffer<PathBuf>)>>
data data
} }
#[derive(serde::Serialize, serde::Deserialize, Debug)] #[derive(serde::Serialize, serde::Deserialize, Debug, Hash)]
pub(crate) struct Attachment<Location> { pub(crate) struct Attachment<Location> {
// The title for this attachment as displayed // The title for this attachment as displayed
pub(crate) title: String, pub(crate) title: String,
@ -196,20 +197,20 @@ pub(crate) struct Attachment<Location> {
pub(crate) attachment_location: Location, pub(crate) attachment_location: Location,
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Hash)]
pub(crate) struct Link { pub(crate) struct Link {
pub(crate) title: String, pub(crate) title: String,
pub(crate) destination: String, pub(crate) destination: String,
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Hash)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum ConfirmationStatus { pub enum ConfirmationStatus {
AwaitingConfirmation { token: String }, AwaitingConfirmation { token: String },
Confirmed, Confirmed,
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Hash)]
pub enum ReviewStatus { pub enum ReviewStatus {
/// Has yet to be reviewed /// Has yet to be reviewed
AwaitingReview, AwaitingReview,
@ -219,7 +220,7 @@ pub enum ReviewStatus {
UnPublished, UnPublished,
} }
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Hash)]
pub struct JobOfferStatus { pub struct JobOfferStatus {
review_status: ReviewStatus, review_status: ReviewStatus,
confirmation_status: ConfirmationStatus, confirmation_status: ConfirmationStatus,
@ -295,6 +296,14 @@ impl JobOfferStatus {
#[serde(try_from = "toml::value::Datetime", into = "toml::value::Datetime")] #[serde(try_from = "toml::value::Datetime", into = "toml::value::Datetime")]
pub(crate) struct Date(pub(crate) toml::value::Date); pub(crate) struct Date(pub(crate) toml::value::Date);
impl Hash for Date {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.day.hash(state);
self.0.month.hash(state);
self.0.year.hash(state);
}
}
impl std::fmt::Debug for Date { impl std::fmt::Debug for Date {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Date") f.debug_struct("Date")
@ -347,6 +356,52 @@ pub struct JobOffer<AttachmentLocation> {
pub(crate) links: Vec<Link>, pub(crate) links: Vec<Link>,
} }
impl Hash for JobOffer<PathBuf> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.title.hash(state);
self.offering_party.hash(state);
self.public_contact_info.hash(state);
// TODO date_of_submission
if let Some(date) = &self.date_of_submission.date {
1.hash(state);
date.day.hash(state);
date.month.hash(state);
date.year.hash(state);
} else {
0.hash(state);
}
if let Some(time) = &self.date_of_submission.time {
1.hash(state);
time.hour.hash(state);
time.minute.hash(state);
time.second.hash(state);
time.nanosecond.hash(state);
} else {
0.hash(state);
}
if let Some(offset) = &self.date_of_submission.offset {
match offset {
Offset::Z => {
1.hash(state);
}
Offset::Custom { hours, minutes } => {
2.hash(state);
hours.hash(state);
minutes.hash(state);
}
}
} else {
0.hash(state);
}
self.date_of_expiry.hash(state);
self.permanent.hash(state);
self.contact_info.hash(state);
self.status.hash(state);
self.attachments.hash(state);
self.links.hash(state);
}
}
impl Deref for JobOffer<PathBuf> { impl Deref for JobOffer<PathBuf> {
type Target = JobOfferStatus; type Target = JobOfferStatus;