1use anyhow::Result;
3use chrono::prelude::*;
4use platform_info::{PlatformInfo, PlatformInfoAPI, UNameAPI};
5use serde::Serialize;
6use std::fs;
7use std::path::Path;
8
9const METADATA_FILE_NAME: &str = "metadata.toml";
11
12#[allow(clippy::doc_markdown)]
14mod built_info {
15 include!(concat!(env!("OUT_DIR"), "/built.rs"));
17}
18
19fn get_git_hash() -> String {
21 let Some(hash) = built_info::GIT_COMMIT_HASH_SHORT else {
22 return "unknown".into();
23 };
24
25 if built_info::GIT_DIRTY == Some(true) {
26 format!("{hash}-dirty")
27 } else {
28 hash.into()
29 }
30}
31
32#[derive(Serialize)]
34struct Metadata<'a> {
35 run: RunMetadata<'a>,
36 program: ProgramMetadata<'a>,
37 platform: PlatformMetadata,
38}
39
40#[derive(Serialize)]
42struct RunMetadata<'a> {
43 model_path: &'a Path,
45 datetime: String,
47}
48
49impl<'a> RunMetadata<'a> {
50 fn new(model_path: &'a Path) -> Self {
51 let dt = Local::now();
52 Self {
53 model_path,
54 datetime: dt.to_rfc2822(),
55 }
56 }
57}
58
59#[derive(Serialize)]
60struct ProgramMetadata<'a> {
61 name: &'a str,
63 version: &'a str,
65 target: &'a str,
67 is_debug: bool,
69 rustc_version: &'a str,
71 build_time_utc: &'a str,
73 git_commit_hash: String,
75}
76
77impl Default for ProgramMetadata<'_> {
78 fn default() -> Self {
79 Self {
80 name: built_info::PKG_NAME,
81 version: built_info::PKG_VERSION,
82 target: built_info::TARGET,
83 is_debug: built_info::DEBUG,
84 rustc_version: built_info::RUSTC_VERSION,
85 build_time_utc: built_info::BUILT_TIME_UTC,
86 git_commit_hash: get_git_hash(),
87 }
88 }
89}
90
91#[derive(Serialize)]
95struct PlatformMetadata {
96 sysname: String,
97 nodename: String,
98 release: String,
99 version: String,
100 machine: String,
101 osname: String,
102}
103
104impl Default for PlatformMetadata {
105 fn default() -> Self {
106 let info = PlatformInfo::new().expect("Unable to determine platform info");
107 Self {
108 sysname: info.sysname().to_string_lossy().into(),
109 nodename: info.nodename().to_string_lossy().into(),
110 release: info.release().to_string_lossy().into(),
111 version: info.version().to_string_lossy().into(),
112 machine: info.machine().to_string_lossy().into(),
113 osname: info.osname().to_string_lossy().into(),
114 }
115 }
116}
117
118pub fn write_metadata(output_path: &Path, model_path: &Path) -> Result<()> {
120 let metadata = Metadata {
121 run: RunMetadata::new(model_path),
122 program: ProgramMetadata::default(),
123 platform: PlatformMetadata::default(),
124 };
125 let file_path = output_path.join(METADATA_FILE_NAME);
126 fs::write(&file_path, toml::to_string(&metadata)?)?;
127
128 Ok(())
129}