use chrono::Utc;
#[cfg(any(feature = "sqlite", feature = "sqlite-dynlib"))]
use rusqlite::ToSql;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{fmt::Display, time::Duration};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct HistoryItemId(pub i64);
impl HistoryItemId {
pub const fn new(i: i64) -> HistoryItemId {
HistoryItemId(i)
}
}
impl Display for HistoryItemId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HistorySessionId(pub(crate) i64);
impl HistorySessionId {
pub(crate) const fn new(i: i64) -> HistorySessionId {
HistorySessionId(i)
}
}
impl Display for HistorySessionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[cfg(any(feature = "sqlite", feature = "sqlite-dynlib"))]
impl ToSql for HistorySessionId {
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
Ok(rusqlite::types::ToSqlOutput::Owned(
rusqlite::types::Value::Integer(self.0),
))
}
}
impl From<HistorySessionId> for i64 {
fn from(id: HistorySessionId) -> Self {
id.0
}
}
pub trait HistoryItemExtraInfo: Serialize + DeserializeOwned + Default + Send {}
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
pub struct IgnoreAllExtraInfo;
impl Serialize for IgnoreAllExtraInfo {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
Option::<IgnoreAllExtraInfo>::None.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for IgnoreAllExtraInfo {
fn deserialize<D>(d: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
serde::de::IgnoredAny::deserialize(d).map(|_| IgnoreAllExtraInfo)
}
}
impl HistoryItemExtraInfo for IgnoreAllExtraInfo {}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct HistoryItem<ExtraInfo: HistoryItemExtraInfo = IgnoreAllExtraInfo> {
pub id: Option<HistoryItemId>,
pub start_timestamp: Option<chrono::DateTime<Utc>>,
pub command_line: String,
pub session_id: Option<HistorySessionId>,
pub hostname: Option<String>,
pub cwd: Option<String>,
pub duration: Option<Duration>,
pub exit_status: Option<i64>,
#[serde(deserialize_with = "Option::<ExtraInfo>::deserialize")]
pub more_info: Option<ExtraInfo>,
}
impl HistoryItem {
pub fn from_command_line(cmd: impl Into<String>) -> HistoryItem {
HistoryItem {
id: None,
start_timestamp: None,
command_line: cmd.into(),
session_id: None,
hostname: None,
cwd: None,
duration: None,
exit_status: None,
more_info: None,
}
}
}