Skip to main content

pdfluent_forms/
flags.rs

1//! Field flags (/Ff) bitfield wrapper (B.1).
2
3// Copyright (c) 2026 Innovation Trigger B.V.
4//
5// PDFluent is available under two licences, at your option: the GNU AGPLv3, or
6// the PDFluent Commercial Licence. See the LICENSE file in this repository --
7// that file travels with the copy you received, which a URL does not.
8
9/// Wrapper around a PDF field-flags integer (/Ff).
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
11pub struct FieldFlags(u32);
12
13impl FieldFlags {
14    /// Create from raw bits.
15    pub fn from_bits(bits: u32) -> Self {
16        Self(bits)
17    }
18    /// Empty (no flags set).
19    pub fn empty() -> Self {
20        Self(0)
21    }
22    /// Raw bits.
23    pub fn bits(self) -> u32 {
24        self.0
25    }
26    fn has(self, bit: u32) -> bool {
27        self.0 & (1 << bit) != 0
28    }
29
30    // Common flags
31    /// Bit 1: read-only.
32    pub fn read_only(self) -> bool {
33        self.has(0)
34    }
35    /// Bit 2: required.
36    pub fn required(self) -> bool {
37        self.has(1)
38    }
39    /// Bit 3: no-export.
40    pub fn no_export(self) -> bool {
41        self.has(2)
42    }
43
44    // Text field flags
45    /// Bit 13: multiline.
46    pub fn multiline(self) -> bool {
47        self.has(12)
48    }
49    /// Bit 14: password.
50    pub fn password(self) -> bool {
51        self.has(13)
52    }
53    /// Bit 21: file-select.
54    pub fn file_select(self) -> bool {
55        self.has(20)
56    }
57    /// Bit 23: do-not-spell-check.
58    pub fn do_not_spell_check(self) -> bool {
59        self.has(22)
60    }
61    /// Bit 24: do-not-scroll.
62    pub fn do_not_scroll(self) -> bool {
63        self.has(23)
64    }
65    /// Bit 25: comb.
66    pub fn comb(self) -> bool {
67        self.has(24)
68    }
69    /// Bit 26: rich-text.
70    pub fn rich_text(self) -> bool {
71        self.has(25)
72    }
73
74    // Button flags
75    /// Bit 15: no-toggle-to-off (radio buttons).
76    pub fn no_toggle_to_off(self) -> bool {
77        self.has(14)
78    }
79    /// Bit 16: radio.
80    pub fn radio(self) -> bool {
81        self.has(15)
82    }
83    /// Bit 17: push-button.
84    pub fn push_button(self) -> bool {
85        self.has(16)
86    }
87    /// Bit 26: radios-in-unison.
88    pub fn radios_in_unison(self) -> bool {
89        self.has(25)
90    }
91
92    // Choice flags
93    /// Bit 18: combo.
94    pub fn combo(self) -> bool {
95        self.has(17)
96    }
97    /// Bit 19: edit (editable combo).
98    pub fn edit(self) -> bool {
99        self.has(18)
100    }
101    /// Bit 20: sort.
102    pub fn sort(self) -> bool {
103        self.has(19)
104    }
105    /// Bit 22: multi-select.
106    pub fn multi_select(self) -> bool {
107        self.has(21)
108    }
109    /// Bit 27: commit-on-sel-change.
110    pub fn commit_on_sel_change(self) -> bool {
111        self.has(26)
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118    #[test]
119    fn empty_flags() {
120        assert!(!FieldFlags::empty().read_only());
121    }
122    #[test]
123    fn read_only() {
124        assert!(FieldFlags::from_bits(1).read_only());
125    }
126    #[test]
127    fn multiline() {
128        assert!(FieldFlags::from_bits(1 << 12).multiline());
129    }
130    #[test]
131    fn combo() {
132        assert!(FieldFlags::from_bits(1 << 17).combo());
133    }
134    #[test]
135    fn push_button() {
136        assert!(FieldFlags::from_bits(1 << 16).push_button());
137    }
138    #[test]
139    fn radio() {
140        assert!(FieldFlags::from_bits(1 << 15).radio());
141    }
142}