Skip to main content

hwpforge_core/control/
fields.rs

1//! Field-control payload types: path/file-name commands, cross-reference
2//! targets, and inline page-number kinds.
3//!
4//! Houses [`PathFieldCommand`], [`RefTarget`], and [`InlinePageKind`] — the
5//! typed payloads carried by the field variants of [`Control`](super::Control).
6
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9
10use crate::object_id::ObjectId;
11
12/// Typed variant of the HWP5 `%pat` Command string (Wave 12n).
13///
14/// Observed forms are `$F` (file name only), `$P` (path only), and `$P$F`
15/// (full path). Anything else is preserved as [`PathFieldCommand::Unknown`].
16#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
17#[non_exhaustive]
18pub enum PathFieldCommand {
19    /// `$F` — file name only.
20    FileName,
21    /// `$P` — folder path only (no file name).
22    Path,
23    /// `$P$F` — full path including file name.
24    PathAndFileName,
25    /// Any other Command form, preserved verbatim.
26    Unknown(String),
27}
28
29impl PathFieldCommand {
30    /// Returns the canonical wire Command string for typed variants.
31    /// For [`Self::Unknown`], returns the carried raw string.
32    pub fn wire_command(&self) -> &str {
33        match self {
34            Self::FileName => "$F",
35            Self::Path => "$P",
36            Self::PathAndFileName => "$P$F",
37            Self::Unknown(s) => s.as_str(),
38        }
39    }
40
41    /// Parses a wire Command string into a typed variant. Unknown forms
42    /// are preserved as [`Self::Unknown`].
43    pub fn from_wire(cmd: &str) -> Self {
44        match cmd {
45            "$F" => Self::FileName,
46            "$P" => Self::Path,
47            "$P$F" => Self::PathAndFileName,
48            other => Self::Unknown(other.to_string()),
49        }
50    }
51}
52
53/// Cross-reference target identifier (Wave 12m Phase 2).
54///
55/// Replaces the previous `target_name: String` field on
56/// [`Control::CrossRef`] with a type-safe enum that distinguishes the
57/// three observed wire forms in HWP5 `%xrf` Command strings:
58///
59/// - **`Name(String)`** — 사용자 지정 책갈피 이름 (Bookmark 전용).
60///   한컴 fixture 의 `?target1;6;0;0;0;` 형식에서 `target1` 부분.
61/// - **`Object(ObjectId)`** — 한컴 자동 생성 정수 ID (Footnote / Endnote /
62///   Caption / Outline). 한컴 fixture 의 `?#1108165575;3;0;0;0;` 형식에서
63///   `#` 접두사를 떼고 정수로 파싱한 값. 가리키는 타깃(Image/Table/…)의
64///   `inst_id: Option<ObjectId>` 와 **같은 [`ObjectId`]** 를 공유해 링크를
65///   타입 수준에서 보장한다 (ADR-010).
66/// - **`Raw(String)`** — 위 두 형식 어느쪽으로도 파싱이 안 된 wire 값.
67///   silent fallback 위조 금지 원칙 (Codex(architect)) — 의미를
68///   모르면 raw 보존.
69///
70/// 변환은 `smithy-hwp5/src/projection.rs::decode_hwp5_target` 의
71/// boundary 함수에서 수행 (Core 는 wire-agnostic).
72#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
73#[non_exhaustive]
74pub enum RefTarget {
75    /// 사용자 지정 책갈피 이름 (Bookmark 전용).
76    Name(String),
77    /// 타깃 객체의 [`ObjectId`] (Footnote / Endnote / Caption / Outline).
78    /// 가리키는 타깃의 `inst_id` 와 같은 id 를 공유한다 (ADR-010).
79    Object(ObjectId),
80    /// 위 형식 어느쪽으로도 정규화되지 않은 raw 값 — fallback 위조 금지.
81    Raw(String),
82}
83
84impl RefTarget {
85    /// Returns the displayable name for this target.
86    ///
87    /// - `Name(s)` → `s`
88    /// - `Object(id)` → `"#{id}"` 형식 (한컴 wire 와 동일)
89    /// - `Raw(s)` → `s`
90    pub fn as_display(&self) -> String {
91        match self {
92            Self::Name(s) => s.clone(),
93            Self::Object(id) => format!("#{id}"),
94            Self::Raw(s) => s.clone(),
95        }
96    }
97}
98
99/// Typed variant of the HWP5 `atno` inline page-number `flag` byte
100/// (Wave 12n).
101///
102/// Observed values: `0x00` = current page, `0x06` = total page count.
103/// Other values surface as [`InlinePageKind::Unknown`].
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
105#[non_exhaustive]
106pub enum InlinePageKind {
107    /// Flag `0x00` — current page number.
108    CurrentPage,
109    /// Flag `0x06` — total page count.
110    TotalPages,
111    /// Any other flag value, surfaced when the HWP5 wire flag is neither
112    /// `0x00` nor `0x06`.
113    Unknown,
114}