build_script/
instruction.rs1use crate::prefix::Prefix;
3use crate::value::Value;
4use std::fmt;
5use std::fmt::Formatter;
6
7#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
9pub struct Instruction {
10 pub prefix: Prefix,
12
13 pub name: Option<String>,
16
17 pub value: Value,
19}
20
21impl Instruction {
22 pub fn new(name: &str, value: Value) -> Self {
25 Self {
26 value,
27 name: Some(name.into()),
28 prefix: Default::default(),
29 }
30 }
31
32 pub fn new_mapping(value: Value) -> Self {
38 if value.is_mapping() || value.is_unquoted_mapping() {
39 Self {
40 value,
41 name: None,
42 prefix: Default::default(),
43 }
44 } else {
45 panic!("value type must be [Unquoted]Mapping")
46 }
47 }
48
49 pub fn prefix(&mut self, prefix: Prefix) -> &mut Self {
51 self.prefix = prefix;
52
53 self
54 }
55
56 pub fn name(&mut self, name: &str) -> &mut Self {
58 self.name = Some(name.into());
59
60 self
61 }
62}
63
64impl fmt::Display for Instruction {
65 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
66 if let Some(name) = &self.name {
67 write!(f, "{}:{}={}", self.prefix, name, self.value)
68 } else if let Value::Mapping(key, value) = &self.value {
69 write!(f, "{}:{}={}", self.prefix, key, value)
70 } else if let Value::UnquotedMapping(key, value) = &self.value {
71 write!(f, "{}:{}={}", self.prefix, key, value)
72 } else {
73 panic!("value type must be [Unquoted]Mapping")
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use crate::{Instruction, Prefix, Value};
81
82 macro_rules! new_wrong_value_test {
83 ($name:ident, $value:expr) => {
84 #[test]
85 #[should_panic]
86 fn $name() {
87 Instruction::new_mapping($value);
88 }
89 };
90 }
91
92 macro_rules! new_right_value_test {
93 ($name:ident, $value:expr) => {
94 #[test]
95 fn $name() {
96 Instruction::new_mapping($value);
97 }
98 };
99 }
100
101 #[test]
102 fn test_new() {
103 let value = Value::Singular("singular".into());
104 let instruction = Instruction::new("name", value);
105 assert!(matches!(instruction.prefix, Prefix::Cargo));
106 assert_eq!(instruction.name.expect("name is none"), "name");
107 assert!(instruction.value.is_singular());
108 }
109
110 #[test]
111 fn test_new_mapping() {
112 let value = Value::Mapping("key".into(), "value".into());
113 let instruction = Instruction::new_mapping(value);
114 assert!(instruction.name.is_none());
115 }
116
117 new_wrong_value_test!(
118 test_new_mapping_fails_if_value_singular,
119 Value::Singular("".into())
120 );
121 new_wrong_value_test!(
122 test_new_mapping_fails_if_value_optional_key,
123 Value::OptionalKey(None, "".into())
124 );
125 new_wrong_value_test!(
126 test_new_mapping_fails_if_value_unquoted_optional_key,
127 Value::UnquotedOptionalKey(None, "".into())
128 );
129 new_wrong_value_test!(
130 test_new_mapping_fails_if_value_optional_value,
131 Value::OptionalValue("".into(), None)
132 );
133 new_wrong_value_test!(
134 test_new_mapping_fails_if_value_unquoted_optional_value,
135 Value::UnquotedOptionalValue("".into(), None)
136 );
137 new_right_value_test!(
138 test_new_mapping_succeeds_if_value_mapping,
139 Value::Mapping("".into(), "".into())
140 );
141 new_right_value_test!(
142 test_new_mapping_succeeds_if_value_unquoted_mapping,
143 Value::UnquotedMapping("".into(), "".into())
144 );
145}