emjudge_judgecore/
quantity.rs

1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use std::fmt;
3use std::ops::{Add, Sub};
4use std::time::Duration;
5
6#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
7pub struct MemorySize(usize);
8
9impl MemorySize {
10    pub fn new(bytes: usize) -> Self {
11        MemorySize(bytes)
12    }
13
14    pub fn as_bytes(&self) -> usize {
15        self.0
16    }
17
18    pub fn as_kilobytes(&self) -> usize {
19        self.0 / 1024
20    }
21
22    pub fn as_megabytes(&self) -> usize {
23        self.as_kilobytes() / 1024
24    }
25
26    pub fn as_gigabytes(&self) -> usize {
27        self.as_megabytes() / 1024
28    }
29}
30
31impl fmt::Display for MemorySize {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        if self.0 % 1024 == 0 {
34            if self.0 % (1024 * 1024) == 0 {
35                if self.0 % (1024 * 1024 * 1024) == 0 {
36                    write!(f, "{}GB", self.as_gigabytes())
37                } else {
38                    write!(f, "{}MB", self.as_megabytes())
39                }
40            } else {
41                write!(f, "{}KB", self.as_kilobytes())
42            }
43        } else {
44            write!(f, "{}B", self.0)
45        }
46    }
47}
48
49impl MemorySize {
50    pub fn from_bytes(value: usize) -> Self {
51        Self::new(value)
52    }
53
54    pub fn from_kilobytes(value: usize) -> Self {
55        MemorySize::new(value * 1024)
56    }
57
58    pub fn from_megabytes(value: usize) -> Self {
59        MemorySize::new(value * 1024 * 1024)
60    }
61
62    pub fn from_gigabytes(value: usize) -> Self {
63        MemorySize::new(value * 1024 * 1024 * 1024)
64    }
65}
66
67impl Add for MemorySize {
68    type Output = Self;
69
70    fn add(self, other: Self) -> Self::Output {
71        MemorySize::new(self.0 + other.0)
72    }
73}
74
75impl Sub for MemorySize {
76    type Output = Self;
77
78    fn sub(self, other: Self) -> Self::Output {
79        if self.0 >= other.0 {
80            MemorySize::new(self.0 - other.0)
81        } else {
82            MemorySize::new(0)
83        }
84    }
85}
86
87impl Serialize for MemorySize {
88    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89    where
90        S: Serializer,
91    {
92        if self.0 % 1024 == 0 {
93            if self.0 % (1024 * 1024) == 0 {
94                if self.0 % (1024 * 1024 * 1024) == 0 {
95                    serializer.serialize_str(format!("{}GB", self.as_gigabytes()).as_str())
96                } else {
97                    serializer.serialize_str(format!("{}MB", self.as_megabytes()).as_str())
98                }
99            } else {
100                serializer.serialize_str(format!("{}KB", self.as_kilobytes()).as_str())
101            }
102        } else {
103            serializer.serialize_str(format!("{}B", self.0).as_str())
104        }
105    }
106}
107
108impl<'de> Deserialize<'de> for MemorySize {
109    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
110    where
111        D: Deserializer<'de>,
112    {
113        struct MemorySizeVisitor;
114
115        impl<'de> serde::de::Visitor<'de> for MemorySizeVisitor {
116            type Value = MemorySize;
117
118            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
119                formatter.write_str("a string representing MemorySize (e.g., '1024B')")
120            }
121
122            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
123            where
124                E: serde::de::Error,
125            {
126                // Implement custom parsing logic based on your serialization format
127                let (number, unit) =
128                    value.split_at(value.trim_end_matches(|c| char::is_alphabetic(c)).len());
129                let bytes = match unit.trim() {
130                    "B" => 1,
131                    "KB" => 1024,
132                    "MB" => 1024 * 1024,
133                    "GB" => 1024 * 1024 * 1024,
134                    _ => return Err(serde::de::Error::custom("Invalid MemorySize unit")),
135                };
136
137                if let Ok(value) = number.parse::<usize>() {
138                    Ok(MemorySize::new(value * bytes))
139                } else {
140                    Err(serde::de::Error::custom("Invalid MemorySize format"))
141                }
142            }
143        }
144        deserializer.deserialize_str(MemorySizeVisitor)
145    }
146}
147
148#[derive(Debug, Eq, PartialOrd, Ord, Clone, Copy, Default, PartialEq)]
149pub struct TimeSpan(u64);
150
151impl TimeSpan {
152    pub fn from_milliseconds(milliseconds: u64) -> Self {
153        TimeSpan(milliseconds)
154    }
155
156    pub fn from_seconds(seconds: u64) -> Self {
157        TimeSpan(seconds * 1_000)
158    }
159
160    pub fn from_minutes(minutes: u64) -> Self {
161        TimeSpan(minutes * 60 * 1_000)
162    }
163
164    pub fn from_hours(hours: u64) -> Self {
165        TimeSpan(hours * 60 * 60 * 1_000)
166    }
167
168    pub fn as_milliseconds(&self) -> u64 {
169        self.0
170    }
171
172    pub fn as_seconds(&self) -> u64 {
173        self.0 / 1_000
174    }
175
176    pub fn as_minutes(&self) -> u64 {
177        self.0 / 60 / 1_000
178    }
179
180    pub fn as_hours(&self) -> u64 {
181        self.0 / 60 / 60 / 1_000
182    }
183}
184
185impl From<Duration> for TimeSpan {
186    fn from(duration: Duration) -> Self {
187        TimeSpan(duration.as_millis() as u64)
188    }
189}
190
191impl From<TimeSpan> for Duration {
192    fn from(timespan: TimeSpan) -> Self {
193        Duration::from_millis(timespan.0)
194    }
195}
196
197impl fmt::Display for TimeSpan {
198    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199        write!(f, "{}ms", self.as_milliseconds())
200    }
201}
202
203impl Serialize for TimeSpan {
204    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
205    where
206        S: Serializer,
207    {
208        if self.0 % 1000 == 0 {
209            if self.0 % (1000 * 60) == 0 {
210                if self.0 % (1000 * 60 * 60) == 0 {
211                    serializer.serialize_str(format!("{}h", self.as_hours()).as_str())
212                } else {
213                    serializer.serialize_str(format!("{}m", self.as_minutes()).as_str())
214                }
215            } else {
216                serializer.serialize_str(format!("{}s", self.as_seconds()).as_str())
217            }
218        } else {
219            serializer.serialize_str(format!("{}ms", self.0).as_str())
220        }
221    }
222}
223
224impl<'de> Deserialize<'de> for TimeSpan {
225    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
226    where
227        D: Deserializer<'de>,
228    {
229        struct TimeSpanVisitor;
230
231        impl<'de> serde::de::Visitor<'de> for TimeSpanVisitor {
232            type Value = TimeSpan; // Change the type to TimeSpan
233
234            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
235                formatter.write_str(
236                    "a string representing TimeSpan (e.g., '60s', '120m', '24h', '500ms')",
237                )
238            }
239
240            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
241            where
242                E: serde::de::Error,
243            {
244                // Implement custom parsing logic based on your serialization format
245                let (number, unit) =
246                    value.split_at(value.trim_end_matches(|c| char::is_alphabetic(c)).len());
247                let ms = match unit.trim() {
248                    "ms" => 1,
249                    "s" => 1000,
250                    "m" => 60 * 1000,
251                    "h" => 60 * 60 * 1000,
252                    _ => return Err(serde::de::Error::custom("Invalid TimeSpan unit")),
253                };
254
255                if let Ok(value) = number.parse::<u64>() {
256                    Ok(TimeSpan::from_milliseconds(value * ms)) // Use TimeSpan::from_milliseconds instead of MemorySize::new
257                } else {
258                    Err(serde::de::Error::custom("Invalid TimeSpan format"))
259                }
260            }
261        }
262        deserializer.deserialize_str(TimeSpanVisitor)
263    }
264}
265
266impl Add for TimeSpan {
267    type Output = Self;
268
269    fn add(self, other: Self) -> Self::Output {
270        TimeSpan(self.0 + other.0)
271    }
272}
273
274impl Sub for TimeSpan {
275    type Output = Self;
276
277    fn sub(self, other: Self) -> Self::Output {
278        TimeSpan(self.0 - other.0)
279    }
280}
281
282#[derive(Debug, Clone, Default, Deserialize, Serialize)]
283pub struct ProcessResource {
284    pub runtime: TimeSpan,
285    pub memory: MemorySize,
286    pub stdout: Vec<u8>,
287    pub stderr: Vec<u8>,
288}
289
290impl ProcessResource {
291    pub fn default() -> Self {
292        ProcessResource {
293            runtime: TimeSpan::default(),
294            memory: MemorySize::default(),
295            stdout: vec![],
296            stderr: vec![],
297        }
298    }
299}
300
301impl fmt::Display for ProcessResource {
302    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303        let stdout_str = String::from_utf8_lossy(&self.stdout);
304        let stderr_str = String::from_utf8_lossy(&self.stderr);
305
306        let stdout_chars: String = stdout_str.chars().take(256).collect();
307        let stderr_chars: String = stderr_str.chars().take(256).collect();
308
309        let stdout_escaped: String = stdout_chars
310            .bytes()
311            .flat_map(std::ascii::escape_default)
312            .map(|b| b as char)
313            .collect();
314        let stderr_escaped: String = stderr_chars
315            .bytes()
316            .flat_map(std::ascii::escape_default)
317            .map(|b| b as char)
318            .collect();
319        let stdout_escaped = if stdout_str.len() > 256 {
320            format!("{}... ({} chars total)", stdout_escaped, stdout_str.len())
321        } else {
322            stdout_escaped
323        };
324        let stderr_escaped = if stderr_str.len() > 256 {
325            format!("{}... ({} chars total)", stderr_escaped, stderr_str.len())
326        } else {
327            stderr_escaped
328        };
329
330        write!(
331            f,
332            "Runtime: {}, Memory: {}, Stdout: {}, Stderr: {}",
333            self.runtime, self.memory, stdout_escaped, stderr_escaped
334        )
335    }
336}