1use crate::error::FoundationError;
4use serde::{Deserialize, Serialize};
5use std::fmt;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
24#[non_exhaustive]
25#[repr(u8)]
26pub enum Flip {
27 #[default]
29 None = 0,
30 Horizontal = 1,
32 Vertical = 2,
34 Both = 3,
36}
37
38impl fmt::Display for Flip {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 match self {
41 Self::None => f.write_str("None"),
42 Self::Horizontal => f.write_str("Horizontal"),
43 Self::Vertical => f.write_str("Vertical"),
44 Self::Both => f.write_str("Both"),
45 }
46 }
47}
48
49impl std::str::FromStr for Flip {
50 type Err = FoundationError;
51
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 match s {
54 "None" | "NONE" | "none" => Ok(Self::None),
55 "Horizontal" | "HORIZONTAL" | "horizontal" => Ok(Self::Horizontal),
56 "Vertical" | "VERTICAL" | "vertical" => Ok(Self::Vertical),
57 "Both" | "BOTH" | "both" => Ok(Self::Both),
58 _ => Err(FoundationError::ParseError {
59 type_name: "Flip".to_string(),
60 value: s.to_string(),
61 valid_values: "None, Horizontal, Vertical, Both".to_string(),
62 }),
63 }
64 }
65}
66
67impl TryFrom<u8> for Flip {
68 type Error = FoundationError;
69
70 fn try_from(value: u8) -> Result<Self, Self::Error> {
71 match value {
72 0 => Ok(Self::None),
73 1 => Ok(Self::Horizontal),
74 2 => Ok(Self::Vertical),
75 3 => Ok(Self::Both),
76 _ => Err(FoundationError::ParseError {
77 type_name: "Flip".to_string(),
78 value: value.to_string(),
79 valid_values: "0 (None), 1 (Horizontal), 2 (Vertical), 3 (Both)".to_string(),
80 }),
81 }
82 }
83}
84
85impl schemars::JsonSchema for Flip {
86 fn schema_name() -> std::borrow::Cow<'static, str> {
87 std::borrow::Cow::Borrowed("Flip")
88 }
89
90 fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
91 gen.subschema_for::<String>()
92 }
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
109#[non_exhaustive]
110#[repr(u8)]
111pub enum ArcType {
112 #[default]
114 Normal = 0,
115 Pie = 1,
117 Chord = 2,
119}
120
121impl fmt::Display for ArcType {
122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 match self {
124 Self::Normal => f.write_str("NORMAL"),
125 Self::Pie => f.write_str("PIE"),
126 Self::Chord => f.write_str("CHORD"),
127 }
128 }
129}
130
131impl std::str::FromStr for ArcType {
132 type Err = FoundationError;
133
134 fn from_str(s: &str) -> Result<Self, Self::Err> {
135 match s {
136 "NORMAL" | "Normal" | "normal" => Ok(Self::Normal),
137 "PIE" | "Pie" | "pie" => Ok(Self::Pie),
138 "CHORD" | "Chord" | "chord" => Ok(Self::Chord),
139 _ => Err(FoundationError::ParseError {
140 type_name: "ArcType".to_string(),
141 value: s.to_string(),
142 valid_values: "NORMAL, PIE, CHORD".to_string(),
143 }),
144 }
145 }
146}
147
148impl TryFrom<u8> for ArcType {
149 type Error = FoundationError;
150
151 fn try_from(value: u8) -> Result<Self, Self::Error> {
152 match value {
153 0 => Ok(Self::Normal),
154 1 => Ok(Self::Pie),
155 2 => Ok(Self::Chord),
156 _ => Err(FoundationError::ParseError {
157 type_name: "ArcType".to_string(),
158 value: value.to_string(),
159 valid_values: "0 (Normal), 1 (Pie), 2 (Chord)".to_string(),
160 }),
161 }
162 }
163}
164
165impl schemars::JsonSchema for ArcType {
166 fn schema_name() -> std::borrow::Cow<'static, str> {
167 std::borrow::Cow::Borrowed("ArcType")
168 }
169
170 fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
171 gen.subschema_for::<String>()
172 }
173}
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
189#[non_exhaustive]
190#[repr(u8)]
191pub enum ArrowType {
192 #[default]
194 None = 0,
195 Normal = 1,
197 Arrow = 2,
199 Concave = 3,
201 Diamond = 4,
203 Oval = 5,
205 Open = 6,
207}
208
209impl fmt::Display for ArrowType {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 match self {
215 Self::None => f.write_str("NORMAL"),
216 Self::Normal => f.write_str("ARROW"),
217 Self::Arrow => f.write_str("SPEAR"),
218 Self::Concave => f.write_str("CONCAVE_ARROW"),
219 Self::Diamond => f.write_str("FILLED_DIAMOND"),
220 Self::Oval => f.write_str("FILLED_CIRCLE"),
221 Self::Open => f.write_str("EMPTY_BOX"),
222 }
223 }
224}
225
226impl std::str::FromStr for ArrowType {
227 type Err = FoundationError;
228
229 fn from_str(s: &str) -> Result<Self, Self::Err> {
230 match s {
232 "NORMAL" => Ok(Self::None),
233 "ARROW" => Ok(Self::Normal),
234 "SPEAR" => Ok(Self::Arrow),
235 "CONCAVE_ARROW" => Ok(Self::Concave),
236 "FILLED_DIAMOND" | "EMPTY_DIAMOND" => Ok(Self::Diamond),
237 "FILLED_CIRCLE" | "EMPTY_CIRCLE" => Ok(Self::Oval),
238 "FILLED_BOX" | "EMPTY_BOX" => Ok(Self::Open),
239 _ => Err(FoundationError::ParseError {
240 type_name: "ArrowType".to_string(),
241 value: s.to_string(),
242 valid_values: "NORMAL, ARROW, SPEAR, CONCAVE_ARROW, FILLED_DIAMOND, EMPTY_DIAMOND, FILLED_CIRCLE, EMPTY_CIRCLE, FILLED_BOX, EMPTY_BOX"
243 .to_string(),
244 }),
245 }
246 }
247}
248
249impl TryFrom<u8> for ArrowType {
250 type Error = FoundationError;
251
252 fn try_from(value: u8) -> Result<Self, Self::Error> {
253 match value {
254 0 => Ok(Self::None),
255 1 => Ok(Self::Normal),
256 2 => Ok(Self::Arrow),
257 3 => Ok(Self::Concave),
258 4 => Ok(Self::Diamond),
259 5 => Ok(Self::Oval),
260 6 => Ok(Self::Open),
261 _ => Err(FoundationError::ParseError {
262 type_name: "ArrowType".to_string(),
263 value: value.to_string(),
264 valid_values:
265 "0 (None), 1 (Normal), 2 (Arrow), 3 (Concave), 4 (Diamond), 5 (Oval), 6 (Open)"
266 .to_string(),
267 }),
268 }
269 }
270}
271
272impl schemars::JsonSchema for ArrowType {
273 fn schema_name() -> std::borrow::Cow<'static, str> {
274 std::borrow::Cow::Borrowed("ArrowType")
275 }
276
277 fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
278 gen.subschema_for::<String>()
279 }
280}
281
282#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
298#[non_exhaustive]
299#[repr(u8)]
300pub enum ArrowSize {
301 Small = 0,
303 #[default]
305 Medium = 1,
306 Large = 2,
308}
309
310impl fmt::Display for ArrowSize {
311 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
312 match self {
313 Self::Small => f.write_str("SMALL_SMALL"),
314 Self::Medium => f.write_str("MEDIUM_MEDIUM"),
315 Self::Large => f.write_str("LARGE_LARGE"),
316 }
317 }
318}
319
320impl std::str::FromStr for ArrowSize {
321 type Err = FoundationError;
322
323 fn from_str(s: &str) -> Result<Self, Self::Err> {
324 match s {
325 "SMALL_SMALL" | "Small" | "small" => Ok(Self::Small),
326 "MEDIUM_MEDIUM" | "Medium" | "medium" => Ok(Self::Medium),
327 "LARGE_LARGE" | "Large" | "large" => Ok(Self::Large),
328 _ => Err(FoundationError::ParseError {
329 type_name: "ArrowSize".to_string(),
330 value: s.to_string(),
331 valid_values: "SMALL_SMALL, MEDIUM_MEDIUM, LARGE_LARGE".to_string(),
332 }),
333 }
334 }
335}
336
337impl TryFrom<u8> for ArrowSize {
338 type Error = FoundationError;
339
340 fn try_from(value: u8) -> Result<Self, Self::Error> {
341 match value {
342 0 => Ok(Self::Small),
343 1 => Ok(Self::Medium),
344 2 => Ok(Self::Large),
345 _ => Err(FoundationError::ParseError {
346 type_name: "ArrowSize".to_string(),
347 value: value.to_string(),
348 valid_values: "0 (Small), 1 (Medium), 2 (Large)".to_string(),
349 }),
350 }
351 }
352}
353
354impl schemars::JsonSchema for ArrowSize {
355 fn schema_name() -> std::borrow::Cow<'static, str> {
356 std::borrow::Cow::Borrowed("ArrowSize")
357 }
358
359 fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
360 gen.subschema_for::<String>()
361 }
362}
363
364#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
378#[non_exhaustive]
379#[repr(u8)]
380pub enum CurveSegmentType {
381 #[default]
383 Line = 0,
384 Curve = 1,
386}
387
388impl fmt::Display for CurveSegmentType {
389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390 match self {
391 Self::Line => f.write_str("LINE"),
392 Self::Curve => f.write_str("CURVE"),
393 }
394 }
395}
396
397impl std::str::FromStr for CurveSegmentType {
398 type Err = FoundationError;
399
400 fn from_str(s: &str) -> Result<Self, Self::Err> {
401 match s {
402 "LINE" | "Line" | "line" => Ok(Self::Line),
403 "CURVE" | "Curve" | "curve" => Ok(Self::Curve),
404 _ => Err(FoundationError::ParseError {
405 type_name: "CurveSegmentType".to_string(),
406 value: s.to_string(),
407 valid_values: "LINE, CURVE".to_string(),
408 }),
409 }
410 }
411}
412
413impl TryFrom<u8> for CurveSegmentType {
414 type Error = FoundationError;
415
416 fn try_from(value: u8) -> Result<Self, Self::Error> {
417 match value {
418 0 => Ok(Self::Line),
419 1 => Ok(Self::Curve),
420 _ => Err(FoundationError::ParseError {
421 type_name: "CurveSegmentType".to_string(),
422 value: value.to_string(),
423 valid_values: "0 (Line), 1 (Curve)".to_string(),
424 }),
425 }
426 }
427}
428
429impl schemars::JsonSchema for CurveSegmentType {
430 fn schema_name() -> std::borrow::Cow<'static, str> {
431 std::borrow::Cow::Borrowed("CurveSegmentType")
432 }
433
434 fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
435 gen.subschema_for::<String>()
436 }
437}
438
439#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
467#[non_exhaustive]
468#[repr(u8)]
469pub enum VerticalAlign {
470 #[default]
472 Top = 0,
473 Center = 1,
475 Bottom = 2,
477}
478
479impl fmt::Display for VerticalAlign {
480 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481 match self {
482 Self::Top => f.write_str("TOP"),
483 Self::Center => f.write_str("CENTER"),
484 Self::Bottom => f.write_str("BOTTOM"),
485 }
486 }
487}
488
489impl std::str::FromStr for VerticalAlign {
490 type Err = FoundationError;
491
492 fn from_str(s: &str) -> Result<Self, Self::Err> {
493 match s {
494 "Top" | "top" | "TOP" => Ok(Self::Top),
495 "Center" | "center" | "CENTER" => Ok(Self::Center),
496 "Bottom" | "bottom" | "BOTTOM" => Ok(Self::Bottom),
497 _ => Err(FoundationError::ParseError {
498 type_name: "VerticalAlign".to_string(),
499 value: s.to_string(),
500 valid_values: "TOP, CENTER, BOTTOM".to_string(),
501 }),
502 }
503 }
504}
505
506impl TryFrom<u8> for VerticalAlign {
507 type Error = FoundationError;
508
509 fn try_from(value: u8) -> Result<Self, Self::Error> {
510 match value {
511 0 => Ok(Self::Top),
512 1 => Ok(Self::Center),
513 2 => Ok(Self::Bottom),
514 _ => Err(FoundationError::ParseError {
515 type_name: "VerticalAlign".to_string(),
516 value: value.to_string(),
517 valid_values: "0 (Top), 1 (Center), 2 (Bottom)".to_string(),
518 }),
519 }
520 }
521}
522
523impl schemars::JsonSchema for VerticalAlign {
524 fn schema_name() -> std::borrow::Cow<'static, str> {
525 std::borrow::Cow::Borrowed("VerticalAlign")
526 }
527
528 fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
529 gen.subschema_for::<String>()
530 }
531}
532
533#[cfg(test)]
534mod vertical_align_tests {
535 use super::VerticalAlign;
536 use std::str::FromStr;
537
538 #[test]
539 fn default_is_top() {
540 assert_eq!(VerticalAlign::default(), VerticalAlign::Top);
541 }
542
543 #[test]
544 fn display_uses_hwpx_tokens() {
545 assert_eq!(VerticalAlign::Top.to_string(), "TOP");
546 assert_eq!(VerticalAlign::Center.to_string(), "CENTER");
547 assert_eq!(VerticalAlign::Bottom.to_string(), "BOTTOM");
548 }
549
550 #[test]
551 fn from_str_accepts_hwpx_and_pascal_and_lower() {
552 assert_eq!(VerticalAlign::from_str("TOP").unwrap(), VerticalAlign::Top);
553 assert_eq!(VerticalAlign::from_str("Center").unwrap(), VerticalAlign::Center);
554 assert_eq!(VerticalAlign::from_str("bottom").unwrap(), VerticalAlign::Bottom);
555 }
556
557 #[test]
558 fn from_str_round_trips_display() {
559 for v in [VerticalAlign::Top, VerticalAlign::Center, VerticalAlign::Bottom] {
560 assert_eq!(VerticalAlign::from_str(&v.to_string()).unwrap(), v);
561 }
562 }
563
564 #[test]
565 fn from_str_rejects_invalid() {
566 assert!(VerticalAlign::from_str("").is_err());
567 assert!(VerticalAlign::from_str("MIDDLE").is_err());
568 assert!(VerticalAlign::from_str("baseline").is_err());
569 }
570
571 #[test]
572 fn try_from_u8_boundaries() {
573 assert_eq!(VerticalAlign::try_from(0u8).unwrap(), VerticalAlign::Top);
574 assert_eq!(VerticalAlign::try_from(1u8).unwrap(), VerticalAlign::Center);
575 assert_eq!(VerticalAlign::try_from(2u8).unwrap(), VerticalAlign::Bottom);
576 assert!(VerticalAlign::try_from(3u8).is_err());
577 assert!(VerticalAlign::try_from(u8::MAX).is_err());
578 }
579
580 #[test]
581 fn is_one_byte() {
582 assert_eq!(std::mem::size_of::<VerticalAlign>(), 1);
583 }
584}