git_bot_feedback/
output_variable.rs1use std::fmt::Display;
2
3use crate::error::OutputVariableError;
4
5#[derive(Debug, Clone)]
13pub struct OutputVariable {
14 pub name: String,
16
17 pub value: String,
19}
20
21impl OutputVariable {
22 pub fn validate(&self) -> Result<(), OutputVariableError> {
27 let name = self.name.trim();
28 if name.is_empty() {
29 return Err(OutputVariableError::NameIsEmpty);
30 }
31 for (i, c) in name.chars().enumerate() {
32 if i == 0 && c.is_ascii_digit() {
33 return Err(OutputVariableError::NameStartsWithNumber(name.to_string()));
34 }
35 if !(c.is_ascii_alphanumeric() || c == '_' || c == '-') {
36 return Err(OutputVariableError::NameContainsNonPrintableCharacters(
37 name.to_string(),
38 ));
39 }
40 }
41 let value = self.value.trim();
42 if !value
43 .chars()
44 .all(|c| c.is_ascii_alphanumeric() || c.is_ascii_punctuation() || !c.is_ascii_control())
45 {
46 return Err(OutputVariableError::ValueContainsNonPrintableCharacters(
47 value.to_string(),
48 ));
49 }
50 Ok(())
51 }
52}
53
54impl Display for OutputVariable {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(f, "{}={}", self.name.trim(), self.value.trim())
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::{OutputVariable, OutputVariableError};
63
64 #[test]
65 fn empty_name() {
66 let var = OutputVariable {
67 name: " ".to_string(),
68 value: "value".to_string(),
69 };
70 assert_eq!(var.validate(), Err(OutputVariableError::NameIsEmpty));
71 }
72
73 #[test]
74 fn name_starts_with_number() {
75 let var = OutputVariable {
76 name: "1var".to_string(),
77 value: "value".to_string(),
78 };
79 assert_eq!(
80 var.validate(),
81 Err(OutputVariableError::NameStartsWithNumber(
82 "1var".to_string()
83 ))
84 );
85 }
86
87 #[test]
88 fn name_contains_non_printable_characters() {
89 let var = OutputVariable {
90 name: "var\nname".to_string(),
91 value: "value".to_string(),
92 };
93 assert_eq!(
94 var.validate(),
95 Err(OutputVariableError::NameContainsNonPrintableCharacters(
96 "var\nname".to_string()
97 ))
98 );
99 }
100
101 #[test]
102 fn value_contains_non_printable_characters() {
103 let var = OutputVariable {
104 name: "var".to_string(),
105 value: "(val)\nline2".to_string(),
106 };
107 assert_eq!(
108 var.validate(),
109 Err(OutputVariableError::ValueContainsNonPrintableCharacters(
110 "(val)\nline2".to_string()
111 ))
112 );
113 }
114
115 #[test]
116 fn valid_variable() {
117 OutputVariable {
118 name: " VAR_NAME ".to_string(),
119 value: " value -(123) ".to_string(),
120 }
121 .validate()
122 .unwrap();
123 }
124}