1use gear_core::{memory::PageBuf, pages::GearPage};
22pub use nonempty::NonEmpty;
23use parity_scale_codec::{Decode, Encode};
24use path_clean::PathClean;
25use serde::{Deserialize, Serialize};
26use std::{
27 env, fs,
28 path::Path,
29 time::{Duration, SystemTime, UNIX_EPOCH},
30};
31
32pub mod codegen;
33
34pub trait RingGet<V> {
41 fn ring_get(&self, index: usize) -> &V;
43}
44
45impl<V> RingGet<V> for NonEmpty<V> {
46 fn ring_get(&self, index: usize) -> &V {
47 self.get(index % self.len()).expect("guaranteed to be some")
49 }
50}
51
52pub fn now_millis() -> u64 {
54 now_duration().as_millis() as u64
55}
56
57pub fn now_micros() -> u128 {
59 now_duration().as_micros()
60}
61
62pub fn now_duration() -> Duration {
64 SystemTime::now()
65 .duration_since(UNIX_EPOCH)
66 .expect("Internal error: current time before UNIX Epoch")
67}
68
69pub fn init_default_logger() {
79 let _ = tracing_subscriber::fmt::try_init();
80}
81
82#[derive(Serialize, Deserialize)]
84pub struct MemoryPageDump {
85 page: u32,
86 data: Option<String>,
87}
88
89impl MemoryPageDump {
90 pub fn new(page_number: GearPage, page_data: PageBuf) -> MemoryPageDump {
91 let mut data_vec = vec![];
92 page_data.encode_to(&mut data_vec);
93 let data = data_vec
94 .iter()
95 .any(|&byte| byte != 0)
96 .then(|| hex::encode(data_vec));
97
98 MemoryPageDump {
99 page: page_number.into(),
100 data,
101 }
102 }
103
104 pub fn into_gear_page(self) -> (GearPage, PageBuf) {
105 let page_buf = if let Some(page_hex) = self.data {
106 let data = hex::decode(page_hex).expect("Unexpected memory page data encoding");
107 PageBuf::decode(&mut &*data).expect("Invalid PageBuf data found")
108 } else {
109 PageBuf::new_zeroed()
110 };
111 (
112 GearPage::try_from(self.page)
113 .unwrap_or_else(|_| panic!("Couldn't decode GearPage from u32: {}", self.page)),
114 page_buf,
115 )
116 }
117}
118
119#[derive(Serialize, Deserialize, Default)]
121pub struct ProgramMemoryDump {
122 pub balance: u128,
123 pub reserved_balance: u128,
124 pub pages: Vec<MemoryPageDump>,
125}
126
127impl ProgramMemoryDump {
128 pub fn save_to_file(&self, path: impl AsRef<Path>) {
129 let path = env::current_dir()
130 .expect("Unable to get root directory of the project")
131 .join(path)
132 .clean();
133
134 if let Some(parent) = path.parent() {
135 fs::create_dir_all(parent)
136 .unwrap_or_else(|_| panic!("Couldn't create folder {}", parent.display()));
137 }
138
139 let data =
140 serde_json::to_string(&self).expect("Failed to serialize ProgramMemoryDump to JSON");
141
142 fs::write(&path, data).unwrap_or_else(|_| panic!("Failed to write file {path:?}"));
143 }
144
145 pub fn load_from_file(path: impl AsRef<Path>) -> ProgramMemoryDump {
146 let path = env::current_dir()
147 .expect("Unable to get root directory of the project")
148 .join(path)
149 .clean();
150
151 let json =
152 fs::read_to_string(&path).unwrap_or_else(|_| panic!("Failed to read file {path:?}"));
153
154 serde_json::from_str(&json)
155 .unwrap_or_else(|_| panic!("Failed to deserialize {path:?} as ProgramMemoryDump"))
156 }
157}