1use anyhow::Result;
8use chrono::prelude::*;
9use platform_info::{PlatformInfo, PlatformInfoAPI, UNameAPI};
10use serde::Serialize;
11use std::fs;
12use std::path::Path;
13
14const METADATA_FILE_NAME: &str = "metadata.toml";
16
17#[allow(clippy::doc_markdown)]
22#[allow(clippy::needless_raw_strings)]
23mod built_info {
24 include!(concat!(env!("OUT_DIR"), "/built.rs"));
26}
27
28fn get_git_hash() -> String {
31 let Some(hash) = built_info::GIT_COMMIT_HASH_SHORT else {
32 return "unknown".into();
33 };
34
35 if built_info::GIT_DIRTY == Some(true) {
36 format!("{hash}-dirty")
37 } else {
38 hash.into()
39 }
40}
41
42#[derive(Serialize)]
47struct Metadata<'a> {
48 run: RunMetadata<'a>,
49 program: ProgramMetadata<'a>,
50 platform: PlatformMetadata,
51}
52
53#[derive(Serialize)]
55struct RunMetadata<'a> {
56 model_path: &'a Path,
58 datetime: String,
60}
61
62impl<'a> RunMetadata<'a> {
63 fn new(model_path: &'a Path) -> Self {
64 let dt = Local::now();
65 Self {
66 model_path,
67 datetime: dt.to_rfc2822(),
68 }
69 }
70}
71
72#[derive(Serialize)]
73struct ProgramMetadata<'a> {
74 name: &'a str,
76 version: &'a str,
78 target: &'a str,
80 is_debug: bool,
82 rustc_version: &'a str,
84 build_time_utc: &'a str,
86 git_commit_hash: String,
88}
89
90impl Default for ProgramMetadata<'_> {
91 fn default() -> Self {
92 Self {
93 name: built_info::PKG_NAME,
94 version: built_info::PKG_VERSION,
95 target: built_info::TARGET,
96 is_debug: built_info::DEBUG,
97 rustc_version: built_info::RUSTC_VERSION,
98 build_time_utc: built_info::BUILT_TIME_UTC,
99 git_commit_hash: get_git_hash(),
100 }
101 }
102}
103
104#[derive(Serialize)]
108struct PlatformMetadata {
109 sysname: String,
110 nodename: String,
111 release: String,
112 version: String,
113 machine: String,
114 osname: String,
115}
116
117impl Default for PlatformMetadata {
118 fn default() -> Self {
119 let info = PlatformInfo::new().expect("Unable to determine platform info");
120 Self {
121 sysname: info.sysname().to_string_lossy().into(),
122 nodename: info.nodename().to_string_lossy().into(),
123 release: info.release().to_string_lossy().into(),
124 version: info.version().to_string_lossy().into(),
125 machine: info.machine().to_string_lossy().into(),
126 osname: info.osname().to_string_lossy().into(),
127 }
128 }
129}
130
131pub fn write_metadata(output_path: &Path, model_path: &Path) -> Result<()> {
142 let metadata = Metadata {
143 run: RunMetadata::new(model_path),
144 program: ProgramMetadata::default(),
145 platform: PlatformMetadata::default(),
146 };
147 let file_path = output_path.join(METADATA_FILE_NAME);
148 fs::write(&file_path, toml::to_string(&metadata)?)?;
149
150 Ok(())
151}