1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
pub mod io; pub mod mail; pub mod smtp; pub type Error = Box<dyn std::error::Error + Send + Sync>; pub type Result<T> = std::result::Result<T, Error>; #[derive(Debug, PartialEq, Eq, Clone)] struct DefaultMailService; impl NamedService for DefaultMailService {} impl EsmtpService for DefaultMailService {} impl MailGuard for DefaultMailService {} impl MailQueue for DefaultMailService {} trait NamedService {} trait EsmtpService {} trait MailGuard {} trait MailQueue {} trait MailService: NamedService + EsmtpService + MailGuard + MailQueue + Sized { fn using<MS: MailSetup<Self>>(self, setup: MS) -> MS::Output { setup.setup(self) } } impl<T> MailService for T where T: NamedService + EsmtpService + MailGuard + MailQueue + Sized {} trait MailSetup<X> { type Output: MailService; fn setup(&self, what: X) -> Self::Output; } #[derive(Debug, PartialEq, Eq, Clone)] struct CompositeMailService<NS, ES, GS, QS> { a: NS, b: ES, c: GS, d: QS, } impl<NS, ES, GS, QS> NamedService for CompositeMailService<NS, ES, GS, QS> where NS: NamedService {} impl<NS, ES, GS, QS> EsmtpService for CompositeMailService<NS, ES, GS, QS> where ES: EsmtpService {} impl<NS, ES, GS, QS> MailGuard for CompositeMailService<NS, ES, GS, QS> where GS: MailGuard {} impl<NS, ES, GS, QS> MailQueue for CompositeMailService<NS, ES, GS, QS> where QS: MailQueue {} struct Setup; use std::ops::Deref; use std::sync::Arc; impl<A> MailSetup<A> for Setup where A: MailService, { type Output = CompositeMailService<Arc<A>, Arc<A>, Arc<A>, DefaultMailService>; fn setup(&self, what: A) -> Self::Output { let arc = Arc::new(what); CompositeMailService { a: arc.clone(), b: arc.clone(), c: arc, d: DefaultMailService, } } } impl<T> NamedService for T where T: Deref, T::Target: NamedService, { } impl<T> EsmtpService for T where T: Deref, T::Target: EsmtpService, { } impl<T> MailGuard for T where T: Deref, T::Target: MailGuard, { } impl<T> MailQueue for T where T: Deref, T::Target: MailQueue, { } #[test] fn test_setup() { let setup = Setup; let svc = DefaultMailService; let composite = setup.setup(svc); hungry(composite); } #[test] fn test_using() { let setup = Setup; let svc = DefaultMailService; let composite = svc.using(setup); hungry(composite); } fn hungry(_svc: impl MailService + Send + Sync + Clone + std::fmt::Debug + 'static) {}