//! Runtime types.
//!
//! This module is used to collect the various supported "runtime types" or
//! "run contexts".

mod sync;

#[cfg(feature = "tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
mod tokio;

#[cfg(feature = "rocket")]
#[cfg_attr(docsrs, doc(cfg(feature = "rocket")))]
mod rocket;

const SVCAPP_INIT_MSG: &str = "Begin service application initialization";
const SVCAPP_TERM_MSG: &str = "Begin service application termination";


pub use sync::{MainParams as SyncMainParams, main as sync_main};

#[cfg(feature = "tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
pub use tokio::{MainParams as TokioMainParams, main as tokio_main};

#[cfg(feature = "rocket")]
#[cfg_attr(docsrs, doc(cfg(feature = "rocket")))]
pub use rocket::{MainParams as RocketMainParams, main as rocket_main};


fn timeit<F, R>(action: &str, f: F) -> R
where
  F: FnOnce() -> R
{
  let start_ts = jiff::Timestamp::now();
  let ret = f();
  let mut span = jiff::Timestamp::now() - start_ts;
  span = autoround_span(span);
  log::debug!("Service {action} ran for {span:#}",);
  ret
}


async fn timeit_async<F, Fut, R>(action: &str, f: F) -> R
where
  F: FnOnce() -> Fut,
  Fut: Future<Output = R>
{
  let start_ts = jiff::Timestamp::now();
  let ret = f().await;
  let mut span = jiff::Timestamp::now() - start_ts;
  span = autoround_span(span);
  log::debug!("Service {action} ran for {span:#}",);
  ret
}


fn rounded_elapse(start_ts: jiff::Timestamp) -> jiff::Span {
  let span = jiff::Timestamp::now() - start_ts;
  autoround_span(span)
}

fn autoround_span(span: jiff::Span) -> jiff::Span {
  let one_second = jiff::Span::new().seconds(1);

  let cmp = match span.abs().compare(one_second) {
    Ok(cmp) => cmp,
    Err(e) => {
      log::error!("Failed to compare spans; {e}");
      return span;
    }
  };
  let smallest_unit = if cmp.is_ge() {
    jiff::Unit::Millisecond
  } else {
    jiff::Unit::Microsecond
  };
  let rounding = jiff::SpanRound::new()
    .smallest(smallest_unit)
    .mode(jiff::RoundMode::Trunc);
  match span.round(rounding) {
    Ok(span) => span,
    Err(e) => {
      log::error!("Failed to truncate elapsed initialization time; {e}");
      span
    }
  }
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :
