Skip to main content

hwpforge_foundation/enums/
page.rs

1//! Page-level enums: page application scope, numbering, gutters, and section restart.
2
3use crate::error::FoundationError;
4use serde::{Deserialize, Serialize};
5use std::fmt;
6
7// ---------------------------------------------------------------------------
8// ApplyPageType
9// ---------------------------------------------------------------------------
10
11/// Which pages a header/footer applies to.
12///
13/// # Examples
14///
15/// ```
16/// use hwpforge_foundation::ApplyPageType;
17///
18/// assert_eq!(ApplyPageType::default(), ApplyPageType::Both);
19/// ```
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
21#[non_exhaustive]
22#[repr(u8)]
23pub enum ApplyPageType {
24    /// Both even and odd pages (default).
25    #[default]
26    Both = 0,
27    /// Even pages only.
28    Even = 1,
29    /// Odd pages only.
30    Odd = 2,
31}
32
33impl fmt::Display for ApplyPageType {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        match self {
36            Self::Both => f.write_str("Both"),
37            Self::Even => f.write_str("Even"),
38            Self::Odd => f.write_str("Odd"),
39        }
40    }
41}
42
43impl std::str::FromStr for ApplyPageType {
44    type Err = FoundationError;
45
46    fn from_str(s: &str) -> Result<Self, Self::Err> {
47        match s {
48            "Both" | "both" | "BOTH" => Ok(Self::Both),
49            "Even" | "even" | "EVEN" => Ok(Self::Even),
50            "Odd" | "odd" | "ODD" => Ok(Self::Odd),
51            _ => Err(FoundationError::ParseError {
52                type_name: "ApplyPageType".to_string(),
53                value: s.to_string(),
54                valid_values: "Both, Even, Odd".to_string(),
55            }),
56        }
57    }
58}
59
60impl TryFrom<u8> for ApplyPageType {
61    type Error = FoundationError;
62
63    fn try_from(value: u8) -> Result<Self, Self::Error> {
64        match value {
65            0 => Ok(Self::Both),
66            1 => Ok(Self::Even),
67            2 => Ok(Self::Odd),
68            _ => Err(FoundationError::ParseError {
69                type_name: "ApplyPageType".to_string(),
70                value: value.to_string(),
71                valid_values: "0 (Both), 1 (Even), 2 (Odd)".to_string(),
72            }),
73        }
74    }
75}
76
77impl schemars::JsonSchema for ApplyPageType {
78    fn schema_name() -> std::borrow::Cow<'static, str> {
79        std::borrow::Cow::Borrowed("ApplyPageType")
80    }
81
82    fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
83        gen.subschema_for::<String>()
84    }
85}
86
87// ---------------------------------------------------------------------------
88// NumberFormatType
89// ---------------------------------------------------------------------------
90
91/// Number format for page numbering.
92///
93/// # Examples
94///
95/// ```
96/// use hwpforge_foundation::NumberFormatType;
97///
98/// assert_eq!(NumberFormatType::default(), NumberFormatType::Digit);
99/// ```
100#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
101#[non_exhaustive]
102#[repr(u8)]
103pub enum NumberFormatType {
104    /// Arabic digits: 1, 2, 3, ... (default).
105    #[default]
106    Digit = 0,
107    /// Circled digits: ①, ②, ③, ...
108    CircledDigit = 1,
109    /// Roman capitals: I, II, III, ...
110    RomanCapital = 2,
111    /// Roman lowercase: i, ii, iii, ...
112    RomanSmall = 3,
113    /// Latin capitals: A, B, C, ...
114    LatinCapital = 4,
115    /// Latin lowercase: a, b, c, ...
116    LatinSmall = 5,
117    /// Hangul syllable: 가, 나, 다, ...
118    HangulSyllable = 6,
119    /// Hangul jamo: ㄱ, ㄴ, ㄷ, ...
120    HangulJamo = 7,
121    /// Hanja digits: 一, 二, 三, ...
122    HanjaDigit = 8,
123    /// Circled Hangul syllable: ㉮, ㉯, ㉰, ... (used for outline level 8).
124    CircledHangulSyllable = 9,
125    /// Circled Latin lowercase: ⓐ, ⓑ, ⓒ, ...
126    CircledLatinSmall = 10,
127}
128
129impl fmt::Display for NumberFormatType {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        match self {
132            Self::Digit => f.write_str("Digit"),
133            Self::CircledDigit => f.write_str("CircledDigit"),
134            Self::RomanCapital => f.write_str("RomanCapital"),
135            Self::RomanSmall => f.write_str("RomanSmall"),
136            Self::LatinCapital => f.write_str("LatinCapital"),
137            Self::LatinSmall => f.write_str("LatinSmall"),
138            Self::HangulSyllable => f.write_str("HangulSyllable"),
139            Self::HangulJamo => f.write_str("HangulJamo"),
140            Self::HanjaDigit => f.write_str("HanjaDigit"),
141            Self::CircledHangulSyllable => f.write_str("CircledHangulSyllable"),
142            Self::CircledLatinSmall => f.write_str("CircledLatinSmall"),
143        }
144    }
145}
146
147impl std::str::FromStr for NumberFormatType {
148    type Err = FoundationError;
149
150    fn from_str(s: &str) -> Result<Self, Self::Err> {
151        match s {
152            "Digit" | "digit" | "DIGIT" => Ok(Self::Digit),
153            "CircledDigit" | "circleddigit" | "CIRCLED_DIGIT" => Ok(Self::CircledDigit),
154            "RomanCapital" | "romancapital" | "ROMAN_CAPITAL" => Ok(Self::RomanCapital),
155            "RomanSmall" | "romansmall" | "ROMAN_SMALL" => Ok(Self::RomanSmall),
156            "LatinCapital" | "latincapital" | "LATIN_CAPITAL" => Ok(Self::LatinCapital),
157            "LatinSmall" | "latinsmall" | "LATIN_SMALL" => Ok(Self::LatinSmall),
158            "HangulSyllable" | "hangulsyllable" | "HANGUL_SYLLABLE" => Ok(Self::HangulSyllable),
159            "HangulJamo" | "hanguljamo" | "HANGUL_JAMO" => Ok(Self::HangulJamo),
160            "HanjaDigit" | "hanjadigit" | "HANJA_DIGIT" => Ok(Self::HanjaDigit),
161            "CircledHangulSyllable" | "circledhangulsyllable" | "CIRCLED_HANGUL_SYLLABLE" => {
162                Ok(Self::CircledHangulSyllable)
163            }
164            "CircledLatinSmall" | "circledlatinsmall" | "CIRCLED_LATIN_SMALL" => {
165                Ok(Self::CircledLatinSmall)
166            }
167            _ => Err(FoundationError::ParseError {
168                type_name: "NumberFormatType".to_string(),
169                value: s.to_string(),
170                valid_values: "Digit, CircledDigit, RomanCapital, RomanSmall, LatinCapital, LatinSmall, HangulSyllable, HangulJamo, HanjaDigit, CircledHangulSyllable, CircledLatinSmall".to_string(),
171            }),
172        }
173    }
174}
175
176impl TryFrom<u8> for NumberFormatType {
177    type Error = FoundationError;
178
179    fn try_from(value: u8) -> Result<Self, Self::Error> {
180        match value {
181            0 => Ok(Self::Digit),
182            1 => Ok(Self::CircledDigit),
183            2 => Ok(Self::RomanCapital),
184            3 => Ok(Self::RomanSmall),
185            4 => Ok(Self::LatinCapital),
186            5 => Ok(Self::LatinSmall),
187            6 => Ok(Self::HangulSyllable),
188            7 => Ok(Self::HangulJamo),
189            8 => Ok(Self::HanjaDigit),
190            9 => Ok(Self::CircledHangulSyllable),
191            10 => Ok(Self::CircledLatinSmall),
192            _ => Err(FoundationError::ParseError {
193                type_name: "NumberFormatType".to_string(),
194                value: value.to_string(),
195                valid_values: "0-10 (Digit, CircledDigit, RomanCapital, RomanSmall, LatinCapital, LatinSmall, HangulSyllable, HangulJamo, HanjaDigit, CircledHangulSyllable, CircledLatinSmall)".to_string(),
196            }),
197        }
198    }
199}
200
201impl schemars::JsonSchema for NumberFormatType {
202    fn schema_name() -> std::borrow::Cow<'static, str> {
203        std::borrow::Cow::Borrowed("NumberFormatType")
204    }
205
206    fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
207        gen.subschema_for::<String>()
208    }
209}
210
211// ---------------------------------------------------------------------------
212// PageNumberPosition
213// ---------------------------------------------------------------------------
214
215/// Position of page numbers on the page.
216///
217/// # Examples
218///
219/// ```
220/// use hwpforge_foundation::PageNumberPosition;
221///
222/// assert_eq!(PageNumberPosition::default(), PageNumberPosition::TopCenter);
223/// ```
224#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
225#[non_exhaustive]
226#[repr(u8)]
227pub enum PageNumberPosition {
228    /// No page number.
229    None = 0,
230    /// Top left.
231    TopLeft = 1,
232    /// Top center (default).
233    #[default]
234    TopCenter = 2,
235    /// Top right.
236    TopRight = 3,
237    /// Bottom left.
238    BottomLeft = 4,
239    /// Bottom center.
240    BottomCenter = 5,
241    /// Bottom right.
242    BottomRight = 6,
243    /// Outside top.
244    OutsideTop = 7,
245    /// Outside bottom.
246    OutsideBottom = 8,
247    /// Inside top.
248    InsideTop = 9,
249    /// Inside bottom.
250    InsideBottom = 10,
251}
252
253impl fmt::Display for PageNumberPosition {
254    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255        match self {
256            Self::None => f.write_str("None"),
257            Self::TopLeft => f.write_str("TopLeft"),
258            Self::TopCenter => f.write_str("TopCenter"),
259            Self::TopRight => f.write_str("TopRight"),
260            Self::BottomLeft => f.write_str("BottomLeft"),
261            Self::BottomCenter => f.write_str("BottomCenter"),
262            Self::BottomRight => f.write_str("BottomRight"),
263            Self::OutsideTop => f.write_str("OutsideTop"),
264            Self::OutsideBottom => f.write_str("OutsideBottom"),
265            Self::InsideTop => f.write_str("InsideTop"),
266            Self::InsideBottom => f.write_str("InsideBottom"),
267        }
268    }
269}
270
271impl std::str::FromStr for PageNumberPosition {
272    type Err = FoundationError;
273
274    fn from_str(s: &str) -> Result<Self, Self::Err> {
275        match s {
276            "None" | "none" | "NONE" => Ok(Self::None),
277            "TopLeft" | "topleft" | "TOP_LEFT" | "top-left" => Ok(Self::TopLeft),
278            "TopCenter" | "topcenter" | "TOP_CENTER" | "top-center" => Ok(Self::TopCenter),
279            "TopRight" | "topright" | "TOP_RIGHT" | "top-right" => Ok(Self::TopRight),
280            "BottomLeft" | "bottomleft" | "BOTTOM_LEFT" | "bottom-left" => Ok(Self::BottomLeft),
281            "BottomCenter" | "bottomcenter" | "BOTTOM_CENTER" | "bottom-center" => {
282                Ok(Self::BottomCenter)
283            }
284            "BottomRight" | "bottomright" | "BOTTOM_RIGHT" | "bottom-right" => {
285                Ok(Self::BottomRight)
286            }
287            "OutsideTop" | "outsidetop" | "OUTSIDE_TOP" | "outside-top" => Ok(Self::OutsideTop),
288            "OutsideBottom" | "outsidebottom" | "OUTSIDE_BOTTOM" | "outside-bottom" => {
289                Ok(Self::OutsideBottom)
290            }
291            "InsideTop" | "insidetop" | "INSIDE_TOP" | "inside-top" => Ok(Self::InsideTop),
292            "InsideBottom" | "insidebottom" | "INSIDE_BOTTOM" | "inside-bottom" => {
293                Ok(Self::InsideBottom)
294            }
295            _ => Err(FoundationError::ParseError {
296                type_name: "PageNumberPosition".to_string(),
297                value: s.to_string(),
298                valid_values: "None, TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter, BottomRight, OutsideTop, OutsideBottom, InsideTop, InsideBottom".to_string(),
299            }),
300        }
301    }
302}
303
304impl TryFrom<u8> for PageNumberPosition {
305    type Error = FoundationError;
306
307    fn try_from(value: u8) -> Result<Self, Self::Error> {
308        match value {
309            0 => Ok(Self::None),
310            1 => Ok(Self::TopLeft),
311            2 => Ok(Self::TopCenter),
312            3 => Ok(Self::TopRight),
313            4 => Ok(Self::BottomLeft),
314            5 => Ok(Self::BottomCenter),
315            6 => Ok(Self::BottomRight),
316            7 => Ok(Self::OutsideTop),
317            8 => Ok(Self::OutsideBottom),
318            9 => Ok(Self::InsideTop),
319            10 => Ok(Self::InsideBottom),
320            _ => Err(FoundationError::ParseError {
321                type_name: "PageNumberPosition".to_string(),
322                value: value.to_string(),
323                valid_values: "0-10 (None, TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter, BottomRight, OutsideTop, OutsideBottom, InsideTop, InsideBottom)".to_string(),
324            }),
325        }
326    }
327}
328
329impl schemars::JsonSchema for PageNumberPosition {
330    fn schema_name() -> std::borrow::Cow<'static, str> {
331        std::borrow::Cow::Borrowed("PageNumberPosition")
332    }
333
334    fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
335        gen.subschema_for::<String>()
336    }
337}
338
339// ---------------------------------------------------------------------------
340// GutterType
341// ---------------------------------------------------------------------------
342
343/// Gutter position type for page margins.
344///
345/// Controls where the binding gutter space is placed on the page.
346/// Used in `<hp:pagePr gutterType="...">`.
347///
348/// # Examples
349///
350/// ```
351/// use hwpforge_foundation::GutterType;
352///
353/// assert_eq!(GutterType::default(), GutterType::LeftOnly);
354/// assert_eq!(GutterType::LeftOnly.to_string(), "LeftOnly");
355/// ```
356#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
357#[non_exhaustive]
358#[repr(u8)]
359pub enum GutterType {
360    /// Gutter on the left side only (default).
361    #[default]
362    LeftOnly = 0,
363    /// Gutter on the left and right sides.
364    LeftRight = 1,
365    /// Gutter on the top side only.
366    TopOnly = 2,
367    /// Gutter on the top and bottom sides.
368    TopBottom = 3,
369}
370
371impl fmt::Display for GutterType {
372    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
373        match self {
374            Self::LeftOnly => f.write_str("LeftOnly"),
375            Self::LeftRight => f.write_str("LeftRight"),
376            Self::TopOnly => f.write_str("TopOnly"),
377            Self::TopBottom => f.write_str("TopBottom"),
378        }
379    }
380}
381
382impl std::str::FromStr for GutterType {
383    type Err = FoundationError;
384
385    fn from_str(s: &str) -> Result<Self, Self::Err> {
386        match s {
387            "LeftOnly" | "LEFT_ONLY" | "left_only" => Ok(Self::LeftOnly),
388            "LeftRight" | "LEFT_RIGHT" | "left_right" => Ok(Self::LeftRight),
389            "TopOnly" | "TOP_ONLY" | "top_only" => Ok(Self::TopOnly),
390            "TopBottom" | "TOP_BOTTOM" | "top_bottom" => Ok(Self::TopBottom),
391            _ => Err(FoundationError::ParseError {
392                type_name: "GutterType".to_string(),
393                value: s.to_string(),
394                valid_values: "LeftOnly, LeftRight, TopOnly, TopBottom".to_string(),
395            }),
396        }
397    }
398}
399
400impl TryFrom<u8> for GutterType {
401    type Error = FoundationError;
402
403    fn try_from(value: u8) -> Result<Self, Self::Error> {
404        match value {
405            0 => Ok(Self::LeftOnly),
406            1 => Ok(Self::LeftRight),
407            2 => Ok(Self::TopOnly),
408            3 => Ok(Self::TopBottom),
409            _ => Err(FoundationError::ParseError {
410                type_name: "GutterType".to_string(),
411                value: value.to_string(),
412                valid_values: "0 (LeftOnly), 1 (LeftRight), 2 (TopOnly), 3 (TopBottom)".to_string(),
413            }),
414        }
415    }
416}
417
418impl schemars::JsonSchema for GutterType {
419    fn schema_name() -> std::borrow::Cow<'static, str> {
420        std::borrow::Cow::Borrowed("GutterType")
421    }
422
423    fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
424        gen.subschema_for::<String>()
425    }
426}
427
428// ---------------------------------------------------------------------------
429// ShowMode
430// ---------------------------------------------------------------------------
431
432/// Visibility mode for page borders and fills.
433///
434/// Controls on which pages the border or fill is displayed.
435/// Used in `<hp:visibility border="..." fill="...">`.
436///
437/// # Examples
438///
439/// ```
440/// use hwpforge_foundation::ShowMode;
441///
442/// assert_eq!(ShowMode::default(), ShowMode::ShowAll);
443/// assert_eq!(ShowMode::ShowAll.to_string(), "ShowAll");
444/// ```
445#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
446#[non_exhaustive]
447#[repr(u8)]
448pub enum ShowMode {
449    /// Show on all pages (default).
450    #[default]
451    ShowAll = 0,
452    /// Hide on all pages.
453    HideAll = 1,
454    /// Show on odd pages only.
455    ShowOdd = 2,
456    /// Show on even pages only.
457    ShowEven = 3,
458}
459
460impl fmt::Display for ShowMode {
461    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
462        match self {
463            Self::ShowAll => f.write_str("ShowAll"),
464            Self::HideAll => f.write_str("HideAll"),
465            Self::ShowOdd => f.write_str("ShowOdd"),
466            Self::ShowEven => f.write_str("ShowEven"),
467        }
468    }
469}
470
471impl std::str::FromStr for ShowMode {
472    type Err = FoundationError;
473
474    fn from_str(s: &str) -> Result<Self, Self::Err> {
475        match s {
476            "ShowAll" | "SHOW_ALL" | "show_all" => Ok(Self::ShowAll),
477            "HideAll" | "HIDE_ALL" | "hide_all" => Ok(Self::HideAll),
478            "ShowOdd" | "SHOW_ODD" | "show_odd" => Ok(Self::ShowOdd),
479            "ShowEven" | "SHOW_EVEN" | "show_even" => Ok(Self::ShowEven),
480            _ => Err(FoundationError::ParseError {
481                type_name: "ShowMode".to_string(),
482                value: s.to_string(),
483                valid_values: "ShowAll, HideAll, ShowOdd, ShowEven".to_string(),
484            }),
485        }
486    }
487}
488
489impl TryFrom<u8> for ShowMode {
490    type Error = FoundationError;
491
492    fn try_from(value: u8) -> Result<Self, Self::Error> {
493        match value {
494            0 => Ok(Self::ShowAll),
495            1 => Ok(Self::HideAll),
496            2 => Ok(Self::ShowOdd),
497            3 => Ok(Self::ShowEven),
498            _ => Err(FoundationError::ParseError {
499                type_name: "ShowMode".to_string(),
500                value: value.to_string(),
501                valid_values: "0 (ShowAll), 1 (HideAll), 2 (ShowOdd), 3 (ShowEven)".to_string(),
502            }),
503        }
504    }
505}
506
507impl schemars::JsonSchema for ShowMode {
508    fn schema_name() -> std::borrow::Cow<'static, str> {
509        std::borrow::Cow::Borrowed("ShowMode")
510    }
511
512    fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
513        gen.subschema_for::<String>()
514    }
515}
516
517// ---------------------------------------------------------------------------
518// RestartType
519// ---------------------------------------------------------------------------
520
521/// Line number restart type.
522///
523/// Controls when line numbering restarts to 1.
524/// Used in `<hp:lineNumberShape restartType="...">`.
525///
526/// # Examples
527///
528/// ```
529/// use hwpforge_foundation::RestartType;
530///
531/// assert_eq!(RestartType::default(), RestartType::Continuous);
532/// assert_eq!(RestartType::Continuous.to_string(), "Continuous");
533/// ```
534#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
535#[non_exhaustive]
536#[repr(u8)]
537pub enum RestartType {
538    /// Continuous numbering throughout the document (default).
539    #[default]
540    Continuous = 0,
541    /// Restart numbering at each section.
542    Section = 1,
543    /// Restart numbering at each page.
544    Page = 2,
545}
546
547impl fmt::Display for RestartType {
548    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549        match self {
550            Self::Continuous => f.write_str("Continuous"),
551            Self::Section => f.write_str("Section"),
552            Self::Page => f.write_str("Page"),
553        }
554    }
555}
556
557impl std::str::FromStr for RestartType {
558    type Err = FoundationError;
559
560    fn from_str(s: &str) -> Result<Self, Self::Err> {
561        match s {
562            "Continuous" | "continuous" | "0" => Ok(Self::Continuous),
563            "Section" | "section" | "1" => Ok(Self::Section),
564            "Page" | "page" | "2" => Ok(Self::Page),
565            _ => Err(FoundationError::ParseError {
566                type_name: "RestartType".to_string(),
567                value: s.to_string(),
568                valid_values: "Continuous, Section, Page".to_string(),
569            }),
570        }
571    }
572}
573
574impl TryFrom<u8> for RestartType {
575    type Error = FoundationError;
576
577    fn try_from(value: u8) -> Result<Self, Self::Error> {
578        match value {
579            0 => Ok(Self::Continuous),
580            1 => Ok(Self::Section),
581            2 => Ok(Self::Page),
582            _ => Err(FoundationError::ParseError {
583                type_name: "RestartType".to_string(),
584                value: value.to_string(),
585                valid_values: "0 (Continuous), 1 (Section), 2 (Page)".to_string(),
586            }),
587        }
588    }
589}
590
591impl schemars::JsonSchema for RestartType {
592    fn schema_name() -> std::borrow::Cow<'static, str> {
593        std::borrow::Cow::Borrowed("RestartType")
594    }
595
596    fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
597        gen.subschema_for::<String>()
598    }
599}