1use alloc::boxed::Box;
2use core::fmt::Display;
3
4#[cfg(not(target_os = "none"))]
5pub use web_time::{Duration, Instant};
6
7#[cfg(target_os = "none")]
8pub use embassy_time::{Duration, Instant};
9
10use crate::future::DynFut;
11
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14#[derive(Debug, Clone, Copy, Eq, PartialEq)]
15pub enum TimingMethod {
16 System,
19 Device,
22}
23
24impl Display for TimingMethod {
25 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
26 match self {
27 TimingMethod::System => f.write_str("system"),
28 TimingMethod::Device => f.write_str("device"),
29 }
30 }
31}
32
33#[derive(Debug)]
35pub struct ProfileTicks {
36 start: Instant,
37 end: Instant,
38}
39
40impl ProfileTicks {
41 pub fn from_start_end(start: Instant, end: Instant) -> Self {
43 Self { start, end }
44 }
45
46 pub fn duration(&self) -> Duration {
48 self.end.duration_since(self.start)
49 }
50
51 pub fn start_duration_since(&self, epoch: Instant) -> Duration {
53 self.start.duration_since(epoch)
54 }
55
56 pub fn end_duration_since(&self, epoch: Instant) -> Duration {
58 self.end.duration_since(epoch)
59 }
60}
61
62pub struct ProfileDuration {
64 future: DynFut<ProfileTicks>,
67 method: TimingMethod,
68}
69
70impl ProfileDuration {
71 pub fn timing_method(&self) -> TimingMethod {
73 self.method
74 }
75
76 pub fn new(future: DynFut<ProfileTicks>, method: TimingMethod) -> ProfileDuration {
78 Self { future, method }
79 }
80
81 pub fn new_system_time(start: Instant, end: Instant) -> Self {
83 Self::new(
84 Box::pin(async move { ProfileTicks::from_start_end(start, end) }),
85 TimingMethod::System,
86 )
87 }
88
89 pub fn new_device_time(
91 future: impl Future<Output = ProfileTicks> + Send + 'static,
92 ) -> ProfileDuration {
93 Self::new(Box::pin(future), TimingMethod::Device)
94 }
95
96 pub fn into_future(self) -> DynFut<ProfileTicks> {
98 self.future
99 }
100
101 pub async fn resolve(self) -> ProfileTicks {
103 self.future.await
104 }
105}