use std::borrow::Cow;
use std::fmt;
use std::net::IpAddr;
use std::str;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use uuid::Uuid;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum SessionStatus {
Ok,
Exited,
Crashed,
Abnormal,
}
impl Default for SessionStatus {
fn default() -> Self {
Self::Ok
}
}
#[derive(Debug, Error)]
#[error("invalid session status")]
pub struct ParseSessionStatusError;
impl str::FromStr for SessionStatus {
type Err = ParseSessionStatusError;
fn from_str(string: &str) -> Result<Self, Self::Err> {
Ok(match string {
"ok" => SessionStatus::Ok,
"crashed" => SessionStatus::Crashed,
"abnormal" => SessionStatus::Abnormal,
"exited" => SessionStatus::Exited,
_ => return Err(ParseSessionStatusError),
})
}
}
impl fmt::Display for SessionStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
SessionStatus::Ok => write!(f, "ok"),
SessionStatus::Crashed => write!(f, "crashed"),
SessionStatus::Abnormal => write!(f, "abnormal"),
SessionStatus::Exited => write!(f, "exited"),
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct SessionAttributes<'a> {
pub release: Cow<'a, str>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub environment: Option<Cow<'a, str>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ip_address: Option<IpAddr>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_agent: Option<String>,
}
fn is_false(val: &bool) -> bool {
!val
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct SessionUpdate<'a> {
#[serde(rename = "sid", default = "Uuid::new_v4")]
pub session_id: Uuid,
#[serde(rename = "did", default)]
pub distinct_id: Option<String>,
#[serde(rename = "seq", default, skip_serializing_if = "Option::is_none")]
pub sequence: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub timestamp: Option<DateTime<Utc>>,
#[serde(default = "Utc::now")]
pub started: DateTime<Utc>,
#[serde(default, skip_serializing_if = "is_false")]
pub init: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub duration: Option<f64>,
#[serde(default)]
pub status: SessionStatus,
#[serde(default)]
pub errors: u64,
#[serde(rename = "attrs")]
pub attributes: SessionAttributes<'a>,
}