1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use castep_cell_fmt::{Cell, CellValue, ToCell, ToCellValue, CResult};
use castep_cell_fmt::parse::FromKeyValue;
/// If present, will cause the current run to be aborted.
/// Implemented as a newtype wrapper around bool.
///
/// Keyword type: Defined (Flag)
///
/// Default: false (not present)
///
/// Example:
/// STOP
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Stop(pub bool);
impl Stop {
/// Creates a new `Stop` instance set to `true`, indicating the flag is present.
pub fn new() -> Self {
Self(true)
}
/// Creates a `Stop` instance set to `false`, indicating the flag is not present.
pub fn not_present() -> Self {
Self(false)
}
}
impl Default for Stop {
fn default() -> Self {
Self::not_present() // Default is not present (false)
}
}
impl FromKeyValue for Stop {
const KEY_NAME: &'static str = "STOP";
fn from_cell_value_kv(_value: &CellValue<'_>) -> CResult<Self> {
Ok(Self(true))
}
}
impl ToCell for Stop {
fn to_cell(&self) -> Cell<'_> {
if self.0 {
Cell::Flag("STOP")
} else {
Cell::Flag("")
}
}
}
// Note: ToCellValue is less applicable for flags, but we can provide a placeholder.
impl ToCellValue for Stop {
fn to_cell_value(&self) -> CellValue<'_> {
// Flags don't have a value in the traditional sense.
// Returning Null or Bool(self.0) could be options.
// Since it's a flag presence, Bool might be more informative if used in a context expecting a value.
CellValue::Bool(self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
use castep_cell_fmt::{ToCell, to_string};
#[test]
fn test_stop_serde() {
// STOP is a flag, typically its presence/absence is what matters.
// Deserialization from "STOP" would ideally create Stop(true).
// Deserialization from nothing means Stop(false) or the field is absent.
// Serialization of Stop(true) should produce Cell::Flag("STOP").
// Serialization of Stop(false) is ambiguous - it shouldn't really be serialized.
// For testing ToCell directly:
let stop_present = Stop::new(); // true
let serialized_string = to_string(&stop_present.to_cell());
println!("Serialized STOP (present):\n{serialized_string}");
assert!(serialized_string.trim() == "STOP"); // Should be just the flag name
let stop_not_present = Stop::not_present(); // false
let serialized_string_not_present = to_string(&stop_not_present.to_cell());
println!("Serialized STOP (not present):\n{serialized_string_not_present}");
// The behavior for serializing Stop(false) is debatable.
// It produces the flag name, which might not be the intended semantics.
// A better model might be `Option<Stop>` in the parent struct.
assert_eq!(Stop::default(), Stop::not_present());
}
}