1use std::convert::TryFrom;
2
3use serde_derive::{Deserialize, Serialize};
4use thiserror::Error;
5
6use crate::db::models as db_models;
7
8#[derive(Debug, Error)]
9pub enum MetaError {
10 #[error("error parsing date: {0}")]
11 Chrono(#[from] chrono::ParseError),
12 #[error("error parsing uuid: {0}")]
13 Uuid(#[from] uuid::Error),
14}
15
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17#[serde(rename_all = "camelCase", deny_unknown_fields)]
18pub struct Meta {
19 pub uuid: uuid::Uuid,
20 #[serde(default = "chrono::Utc::now")]
21 pub created_at: chrono::DateTime<chrono::Utc>,
22}
23
24impl Default for Meta {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl Meta {
31 pub fn new() -> Self {
32 let intf = pnet::datalink::interfaces()
33 .iter()
34 .find_map(|intf| if !intf.is_loopback() { intf.mac } else { None })
35 .unwrap_or_else(pnet::datalink::MacAddr::default);
36
37 Self {
38 uuid: uuid::Uuid::new_v5(&uuid::Uuid::default(), format!("{}", intf).as_bytes()),
39 created_at: chrono::Utc::now(),
40 }
41 }
42}
43
44impl TryFrom<db_models::DbMeta> for Meta {
45 type Error = MetaError;
46
47 fn try_from(db: db_models::DbMeta) -> Result<Self, Self::Error> {
48 Ok(Self {
49 uuid: uuid::Uuid::parse_str(&db.uuid)?,
50 created_at: chrono::DateTime::parse_from_rfc3339(&db.created_at)?
51 .with_timezone(&chrono::Utc),
52 })
53 }
54}