Skip to main content

qubit_codec_misc/
hex_codec_config.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Configuration shared by hexadecimal byte codecs.
9
10/// Configuration shared by [`crate::HexCodec`] encoding and decoding
11/// operations.
12///
13/// The configuration is intentionally separate from the codec value so the
14/// same formatting and decoding policy can be reused by multiple codecs.
15#[must_use]
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct HexCodecConfig {
18    /// Whether to use uppercase hexadecimal digits while encoding.
19    pub(crate) uppercase: bool,
20    /// The prefix to use before the whole encoded string.
21    pub(crate) prefix: Option<String>,
22    /// The prefix to use before each encoded byte.
23    pub(crate) byte_prefix: Option<String>,
24    /// The separator to use between bytes in the encoded string.
25    pub(crate) separator: Option<String>,
26    /// Whether to ignore ASCII whitespace while decoding.
27    pub(crate) ignore_ascii_whitespace: bool,
28    /// Whether to ignore ASCII case when matching configured prefixes.
29    pub(crate) ignore_prefix_case: bool,
30}
31
32impl HexCodecConfig {
33    /// Creates a lowercase configuration without prefixes or separators.
34    #[inline]
35    pub fn new() -> Self {
36        Self {
37            uppercase: false,
38            prefix: None,
39            byte_prefix: None,
40            separator: None,
41            ignore_ascii_whitespace: false,
42            ignore_prefix_case: false,
43        }
44    }
45
46    /// Sets whether encoded digits should be uppercase.
47    #[inline]
48    pub fn with_uppercase(mut self, uppercase: bool) -> Self {
49        self.uppercase = uppercase;
50        self
51    }
52
53    /// Sets a whole-output prefix.
54    #[inline]
55    pub fn with_prefix(mut self, prefix: impl Into<String>) -> Self {
56        self.prefix = Some(prefix.into());
57        self
58    }
59
60    /// Sets a per-byte prefix.
61    #[inline]
62    pub fn with_byte_prefix(mut self, prefix: impl Into<String>) -> Self {
63        self.byte_prefix = Some(prefix.into());
64        self
65    }
66
67    /// Sets a separator between encoded bytes.
68    #[inline]
69    pub fn with_separator(mut self, separator: impl Into<String>) -> Self {
70        self.separator = Some(separator.into());
71        self
72    }
73
74    /// Sets whether ASCII whitespace is ignored while decoding.
75    #[inline]
76    pub fn with_ignored_ascii_whitespace(mut self, ignore: bool) -> Self {
77        self.ignore_ascii_whitespace = ignore;
78        self
79    }
80
81    /// Sets whether configured prefixes are matched case-insensitively.
82    #[inline]
83    pub fn with_ignore_prefix_case(mut self, ignore: bool) -> Self {
84        self.ignore_prefix_case = ignore;
85        self
86    }
87
88    /// Returns whether encoded digits use uppercase characters.
89    #[must_use]
90    #[inline]
91    pub fn is_uppercase(&self) -> bool {
92        self.uppercase
93    }
94
95    /// Returns the configured whole-output prefix.
96    #[must_use]
97    #[inline]
98    pub fn prefix(&self) -> Option<&str> {
99        self.prefix.as_deref()
100    }
101
102    /// Returns the configured per-byte prefix.
103    #[must_use]
104    #[inline]
105    pub fn byte_prefix(&self) -> Option<&str> {
106        self.byte_prefix.as_deref()
107    }
108
109    /// Returns the configured separator.
110    #[must_use]
111    #[inline]
112    pub fn separator(&self) -> Option<&str> {
113        self.separator.as_deref()
114    }
115
116    /// Returns whether ASCII whitespace is ignored while decoding.
117    #[must_use]
118    #[inline]
119    pub fn ignores_ascii_whitespace(&self) -> bool {
120        self.ignore_ascii_whitespace
121    }
122
123    /// Returns whether configured prefixes are matched case-insensitively.
124    #[must_use]
125    #[inline]
126    pub fn ignores_prefix_case(&self) -> bool {
127        self.ignore_prefix_case
128    }
129}
130
131impl Default for HexCodecConfig {
132    #[inline]
133    fn default() -> Self {
134        Self::new()
135    }
136}