1use crate::BBox;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub enum FieldType {
15 Text,
17 Button,
19 Choice,
21 Signature,
23}
24
25impl FieldType {
26 pub fn from_pdf_name(name: &str) -> Option<Self> {
30 match name {
31 "Tx" => Some(Self::Text),
32 "Btn" => Some(Self::Button),
33 "Ch" => Some(Self::Choice),
34 "Sig" => Some(Self::Signature),
35 _ => None,
36 }
37 }
38
39 pub fn as_pdf_name(&self) -> &'static str {
41 match self {
42 Self::Text => "Tx",
43 Self::Button => "Btn",
44 Self::Choice => "Ch",
45 Self::Signature => "Sig",
46 }
47 }
48}
49
50impl std::fmt::Display for FieldType {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 match self {
53 Self::Text => write!(f, "Text"),
54 Self::Button => write!(f, "Button"),
55 Self::Choice => write!(f, "Choice"),
56 Self::Signature => write!(f, "Signature"),
57 }
58 }
59}
60
61#[derive(Debug, Clone, PartialEq)]
66#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67pub struct FormField {
68 pub name: String,
70 pub field_type: FieldType,
72 pub value: Option<String>,
74 pub default_value: Option<String>,
76 pub bbox: BBox,
78 pub options: Vec<String>,
80 pub flags: u32,
82 pub page_index: Option<usize>,
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn field_type_from_pdf_name_text() {
92 assert_eq!(FieldType::from_pdf_name("Tx"), Some(FieldType::Text));
93 }
94
95 #[test]
96 fn field_type_from_pdf_name_button() {
97 assert_eq!(FieldType::from_pdf_name("Btn"), Some(FieldType::Button));
98 }
99
100 #[test]
101 fn field_type_from_pdf_name_choice() {
102 assert_eq!(FieldType::from_pdf_name("Ch"), Some(FieldType::Choice));
103 }
104
105 #[test]
106 fn field_type_from_pdf_name_signature() {
107 assert_eq!(FieldType::from_pdf_name("Sig"), Some(FieldType::Signature));
108 }
109
110 #[test]
111 fn field_type_from_pdf_name_unknown() {
112 assert_eq!(FieldType::from_pdf_name("Unknown"), None);
113 }
114
115 #[test]
116 fn field_type_as_pdf_name() {
117 assert_eq!(FieldType::Text.as_pdf_name(), "Tx");
118 assert_eq!(FieldType::Button.as_pdf_name(), "Btn");
119 assert_eq!(FieldType::Choice.as_pdf_name(), "Ch");
120 assert_eq!(FieldType::Signature.as_pdf_name(), "Sig");
121 }
122
123 #[test]
124 fn field_type_display() {
125 assert_eq!(format!("{}", FieldType::Text), "Text");
126 assert_eq!(format!("{}", FieldType::Button), "Button");
127 assert_eq!(format!("{}", FieldType::Choice), "Choice");
128 assert_eq!(format!("{}", FieldType::Signature), "Signature");
129 }
130
131 #[test]
132 fn form_field_text_with_value() {
133 let field = FormField {
134 name: "full_name".to_string(),
135 field_type: FieldType::Text,
136 value: Some("John Doe".to_string()),
137 default_value: None,
138 bbox: BBox::new(50.0, 100.0, 200.0, 120.0),
139 options: vec![],
140 flags: 0,
141 page_index: Some(0),
142 };
143 assert_eq!(field.name, "full_name");
144 assert_eq!(field.field_type, FieldType::Text);
145 assert_eq!(field.value.as_deref(), Some("John Doe"));
146 assert!(field.default_value.is_none());
147 assert!(field.options.is_empty());
148 assert_eq!(field.flags, 0);
149 assert_eq!(field.page_index, Some(0));
150 }
151
152 #[test]
153 fn form_field_checkbox() {
154 let field = FormField {
155 name: "agree".to_string(),
156 field_type: FieldType::Button,
157 value: Some("Yes".to_string()),
158 default_value: Some("Off".to_string()),
159 bbox: BBox::new(30.0, 200.0, 50.0, 220.0),
160 options: vec![],
161 flags: 0,
162 page_index: Some(0),
163 };
164 assert_eq!(field.field_type, FieldType::Button);
165 assert_eq!(field.value.as_deref(), Some("Yes"));
166 assert_eq!(field.default_value.as_deref(), Some("Off"));
167 }
168
169 #[test]
170 fn form_field_dropdown_with_options() {
171 let field = FormField {
172 name: "country".to_string(),
173 field_type: FieldType::Choice,
174 value: Some("US".to_string()),
175 default_value: None,
176 bbox: BBox::new(50.0, 300.0, 200.0, 320.0),
177 options: vec!["US".to_string(), "UK".to_string(), "FR".to_string()],
178 flags: 0,
179 page_index: Some(0),
180 };
181 assert_eq!(field.field_type, FieldType::Choice);
182 assert_eq!(field.options.len(), 3);
183 assert_eq!(field.options[0], "US");
184 assert_eq!(field.options[2], "FR");
185 }
186
187 #[test]
188 fn form_field_with_no_value() {
189 let field = FormField {
190 name: "email".to_string(),
191 field_type: FieldType::Text,
192 value: None,
193 default_value: None,
194 bbox: BBox::new(50.0, 400.0, 200.0, 420.0),
195 options: vec![],
196 flags: 0,
197 page_index: None,
198 };
199 assert!(field.value.is_none());
200 assert!(field.page_index.is_none());
201 }
202
203 #[test]
204 fn form_field_signature() {
205 let field = FormField {
206 name: "signature".to_string(),
207 field_type: FieldType::Signature,
208 value: None,
209 default_value: None,
210 bbox: BBox::new(100.0, 500.0, 300.0, 600.0),
211 options: vec![],
212 flags: 0,
213 page_index: Some(1),
214 };
215 assert_eq!(field.field_type, FieldType::Signature);
216 }
217
218 #[test]
219 fn form_field_with_flags() {
220 let field = FormField {
221 name: "readonly_field".to_string(),
222 field_type: FieldType::Text,
223 value: Some("Cannot edit".to_string()),
224 default_value: None,
225 bbox: BBox::new(50.0, 100.0, 200.0, 120.0),
226 options: vec![],
227 flags: 1, page_index: Some(0),
229 };
230 assert_eq!(field.flags, 1);
231 }
232
233 #[test]
234 fn form_field_clone_and_eq() {
235 let field1 = FormField {
236 name: "test".to_string(),
237 field_type: FieldType::Text,
238 value: Some("val".to_string()),
239 default_value: None,
240 bbox: BBox::new(0.0, 0.0, 100.0, 20.0),
241 options: vec![],
242 flags: 0,
243 page_index: Some(0),
244 };
245 let field2 = field1.clone();
246 assert_eq!(field1, field2);
247 }
248}