use crate::pagination::{Pagination, SearchPagination}; use hyaenidae_profiles::store::{Comment, File, Profile, Report, ReportKind, Server, Submission}; use std::collections::HashMap; use uuid::Uuid; pub(super) struct ReportPager<'b> { pub(super) store: &'b hyaenidae_profiles::store::Store, pub(super) reports: &'b mut HashMap, pub(super) profiles: &'b mut HashMap, pub(super) submissions: &'b mut HashMap, pub(super) comments: &'b mut HashMap, pub(super) files: &'b mut HashMap, } pub(super) struct OpenPager<'b>(pub(super) ReportPager<'b>); pub(super) struct ClosedPager<'b>(pub(super) ReportPager<'b>); pub(super) struct ServerPager<'b> { pub(super) self_id: Uuid, pub(super) store: &'b hyaenidae_profiles::store::Store, pub(super) servers: &'b mut HashMap, } pub(super) struct FederatedPager<'a>(pub(super) ServerPager<'a>); pub(super) struct InboundPager<'a>(pub(super) ServerPager<'a>); pub(super) struct OutboundPager<'a>(pub(super) ServerPager<'a>); pub(super) struct BlockedPager<'a>(pub(super) ServerPager<'a>); pub(super) struct KnownPager<'a>(pub(super) ServerPager<'a>); impl<'b> Pagination for OpenPager<'b> { fn from_max<'a>(&'a mut self, max: Uuid) -> Box + 'a> { Box::new( self.0 .store .reports .open_reports_older_than(max) .filter_map(move |report_id| self.0.filter_report(report_id)), ) } fn from_min<'a>(&'a mut self, min: Uuid) -> Box + 'a> { Box::new( self.0 .store .reports .open_reports_newer_than(min) .filter_map(move |report_id| self.0.filter_report(report_id)), ) } fn from_start<'a>(&'a mut self) -> Box + 'a> { Box::new( self.0 .store .reports .open_reports() .filter_map(move |report_id| self.0.filter_report(report_id)), ) } } impl<'b> Pagination for ClosedPager<'b> { fn from_max<'a>(&'a mut self, max: Uuid) -> Box + 'a> { Box::new( self.0 .store .reports .closed_reports_older_than(max) .filter_map(move |report_id| self.0.filter_report(report_id)), ) } fn from_min<'a>(&'a mut self, min: Uuid) -> Box + 'a> { Box::new( self.0 .store .reports .closed_reports_newer_than(min) .filter_map(move |report_id| self.0.filter_report(report_id)), ) } fn from_start<'a>(&'a mut self) -> Box + 'a> { Box::new( self.0 .store .reports .closed_reports() .filter_map(move |report_id| self.0.filter_report(report_id)), ) } } impl<'b> ReportPager<'b> { fn filter_report(&mut self, report_id: Uuid) -> Option { if !self.reports.contains_key(&report_id) { let report = self.store.reports.by_id(report_id).ok()??; if let Some(id) = report.reporter_profile() { self.cache_profile(id)?; } match report.kind() { ReportKind::Profile => { self.cache_profile(report.item())?; } ReportKind::Submission => { self.cache_submission(report.item())?; } ReportKind::Comment => { self.cache_comment(report.item())?; } ReportKind::Post => { unimplemented!(); } } self.reports.insert(report.id(), report); Some(report_id) } else { None } } fn cache_comment(&mut self, comment_id: Uuid) -> Option<()> { if !self.comments.contains_key(&comment_id) { let comment = self.store.comments.by_id(comment_id).ok()??; self.cache_profile(comment.profile_id())?; self.comments.insert(comment.id(), comment); } Some(()) } fn cache_submission(&mut self, submission_id: Uuid) -> Option<()> { if !self.submissions.contains_key(&submission_id) { let submission = self.store.submissions.by_id(submission_id).ok()??; self.cache_profile(submission.profile_id())?; for file_id in submission.files() { self.cache_file(*file_id)?; } self.submissions.insert(submission.id(), submission); } Some(()) } fn cache_profile(&mut self, profile_id: Uuid) -> Option<()> { if !self.profiles.contains_key(&profile_id) { let profile = self.store.profiles.by_id(profile_id).ok()??; for file_id in profile.icon().into_iter().chain(profile.banner()) { self.cache_file(file_id)?; } self.profiles.insert(profile.id(), profile); } Some(()) } fn cache_file(&mut self, file_id: Uuid) -> Option<()> { if !self.files.contains_key(&file_id) { let file = self.store.files.by_id(file_id).ok()??; self.files.insert(file.id(), file); } Some(()) } } impl<'b> SearchPagination for FederatedPager<'b> { fn from_term<'a>(&'a mut self, _: &'a str) -> Box + 'a> { Box::new( self.0 .store .view .server_follows .forward_iter(self.0.self_id) .chain( self.0 .store .view .server_follows .backward_iter(self.0.self_id), ) .filter_map(move |server_id| self.0.filter_server(server_id)) .rev(), ) } } impl<'b> SearchPagination for InboundPager<'b> { fn from_term<'a>(&'a mut self, _: &'a str) -> Box + 'a> { Box::new( self.0 .store .view .server_follow_requests .forward_iter(self.0.self_id) .filter_map(move |server_id| self.0.filter_server(server_id)) .rev(), ) } } impl<'b> SearchPagination for OutboundPager<'b> { fn from_term<'a>(&'a mut self, _: &'a str) -> Box + 'a> { Box::new( self.0 .store .view .server_follow_requests .backward_iter(self.0.self_id) .filter_map(move |server_id| self.0.filter_server(server_id)) .rev(), ) } } impl<'b> SearchPagination for BlockedPager<'b> { fn from_term<'a>(&'a mut self, _: &'a str) -> Box + 'a> { Box::new( self.0 .store .view .server_blocks .backward_iter(self.0.self_id) .filter_map(move |server_id| self.0.filter_server(server_id)) .rev(), ) } } impl<'b> SearchPagination for KnownPager<'b> { fn from_term<'a>(&'a mut self, _: &'a str) -> Box + 'a> { Box::new( self.0 .store .servers .known() .filter_map(move |server_id| self.0.filter_server(server_id)) .rev(), ) } } impl<'b> ServerPager<'b> { fn filter_server(&mut self, server_id: Uuid) -> Option { if !self.servers.contains_key(&server_id) { let server = self.store.servers.by_id(server_id).ok()??; self.servers.insert(server.id(), server); Some(server_id) } else { None } } }