1use std::{fs::File, io::BufWriter};
2
3use crate::{LogEntry, ENDPOINT_TYPE, LOGGER};
4
5pub trait EndpointSuper: std::any::Any + std::fmt::Debug + std::marker::Send {}
9impl<T: std::any::Any + std::fmt::Debug + std::marker::Send> EndpointSuper for T {}
10
11pub(crate) trait EndpointExt: EndpointSuper {
12 fn endpoint_hash(&self) -> EndpointHash;
13 fn fmt_message(&self, message: String) -> String;
14}
15
16impl<T: EndpointSuper + std::hash::Hash> EndpointExt for T {
17 fn endpoint_hash(&self) -> EndpointHash {
18 use std::hash::Hasher;
19
20 assert_eq!(ENDPOINT_TYPE.lock().unwrap().unwrap(), self.type_id());
21
22 let mut hasher = std::collections::hash_map::DefaultHasher::new();
23 self.hash(&mut hasher);
24 EndpointHash(hasher.finish())
25 }
26
27 fn fmt_message(&self, message: String) -> String {
28 let mut guard = LOGGER.lock().unwrap();
29 let logger = guard.as_mut().expect("Uninitialized logger. Did you forget to call `aether::init` or did you drop the `KeepAlive` object early?");
30 let fmt = logger
31 .fmt
32 .downcast_ref::<fn(LogEntry<T>) -> String>()
33 .unwrap();
34 fmt(LogEntry {
35 time: chrono::Utc::now(),
36 endpoint: self,
37 text: &message,
38 })
39 }
40}
41
42#[derive(Clone, Copy, Hash, PartialEq, Eq)]
43#[doc(hidden)]
44pub struct EndpointHash(u64);
45
46#[derive(Default)]
47pub(crate) struct Endpoint {
48 pub(crate) file: Option<BufWriter<File>>,
49 pub(crate) silent: bool,
50 pub(crate) disabled: bool,
51}