Skip to main content

libmqm_constants/
impl_types.rs

1use libmqm_sys as mq;
2
3use crate::constants;
4use crate::lookup::{ConstLookup, ConstSource, ConstantItem, HasMqNames as _, LinearSource};
5use crate::mapping;
6use crate::types;
7
8use super::value::{impl_default_value, impl_equivalent_type};
9
10#[cfg(feature = "pcf")]
11mod pcf {
12    use crate::types;
13    use crate::value::impl_equivalent_type;
14
15    impl_equivalent_type!(types::MQIACF, types::Selector);
16    impl_equivalent_type!(types::MQCACF, types::Selector);
17    impl_equivalent_type!(types::MQIACH, types::Selector);
18    impl_equivalent_type!(types::MQCACH, types::Selector);
19
20    impl_equivalent_type!(types::Selector, [types::MQIACF, types::MQCACF, types::MQIACH, types::MQCACH]);
21}
22
23#[cfg(feature = "mqai")]
24mod mqia {
25    use crate::value::{impl_default_value, impl_equivalent_type};
26    use crate::{constants, types};
27
28    impl_default_value!(types::MQIND, constants::MQIND_NONE);
29
30    impl_equivalent_type!(types::MQIASY, types::Selector);
31    impl_equivalent_type!(types::MQHA, types::Selector);
32    impl_equivalent_type!(types::Selector, [types::MQIASY, types::MQHA]);
33}
34
35impl_equivalent_type!(types::MQIA, types::Selector);
36impl_equivalent_type!(types::MQCA, types::Selector);
37impl_equivalent_type!(types::Selector, [types::MQIA, types::MQCA]);
38
39impl_default_value!(types::MQCO, constants::MQCO_NONE);
40impl_default_value!(types::MQBO, constants::MQBO_NONE);
41impl_default_value!(types::MQTYPE, constants::MQTYPE_AS_SET);
42impl_default_value!(types::MQENC, constants::MQENC_NATIVE);
43impl_default_value!(types::MQGMO, constants::MQGMO_NONE);
44impl_default_value!(types::MQPMO, constants::MQPMO_NONE);
45impl_default_value!(types::MQCMHO, constants::MQCMHO_DEFAULT_VALIDATION);
46impl_default_value!(types::MQSMPO, constants::MQSMPO_SET_FIRST);
47impl_default_value!(types::MQDMPO, constants::MQDMPO_DEL_FIRST);
48impl_default_value!(types::MQIMPO, constants::MQIMPO_NONE);
49impl_default_value!(types::MQDCC, constants::MQDCC_NONE);
50#[cfg(feature = "pcf")]
51impl_default_value!(types::MQCMD, constants::MQCMD_NONE);
52
53const FIRST_LAST_MAPSTR: LinearSource = ConstSource(
54    &[
55        (mq::MQBA_FIRST, "MQBA_FIRST"),
56        (mq::MQBA_LAST, "MQBA_LAST"),
57        (mq::MQGA_FIRST, "MQGA_FIRST"),
58        (mq::MQGA_LAST, "MQGA_LAST"),
59        #[cfg(feature = "mqai")]
60        (libmqm_sys::mqai::MQOA_FIRST, "MQOA_FIRST"),
61        #[cfg(feature = "mqai")]
62        (libmqm_sys::mqai::MQOA_LAST, "MQOA_LAST"),
63        #[cfg(feature = "pcf")]
64        (libmqm_sys::pcf::MQUA_FIRST, "MQUA_FIRST"),
65        #[cfg(feature = "pcf")]
66        (libmqm_sys::pcf::MQUA_LAST, "MQUA_LAST"),
67    ],
68    &[],
69);
70
71impl types::MQRC {
72    #[must_use]
73    pub fn ibm_reference_url(&self, language: &str, version: Option<&str>) -> Option<String> {
74        let name = self.mq_primary_name()?.to_lowercase().replace('_', "-");
75        let version = version.unwrap_or("latest");
76        let code = self.0;
77        Some(format!(
78            "https://www.ibm.com/docs/{language}/ibm-mq/{version}?topic=codes-{code}-{code:04x}-rc{code}-{name}"
79        ))
80    }
81}
82
83#[cfg(feature = "pcf")]
84impl_equivalent_type!(types::MQRC, types::MQRCCF);
85
86#[cfg(feature = "pcf")]
87impl_equivalent_type!(types::MQRCCF, types::MQRC);
88
89impl types::MQXA {
90    #[inline]
91    #[must_use]
92    pub const fn is_text(&self) -> bool {
93        self.0 >= constants::MQCA_FIRST.0 && self.0 <= constants::MQCA_LAST.0
94    }
95
96    #[inline]
97    #[must_use]
98    pub const fn is_int(&self) -> bool {
99        self.0 >= constants::MQIA_FIRST.0 && self.0 <= constants::MQIA_LAST.0
100    }
101}
102
103impl_equivalent_type!(types::MQXA, [types::MQCA, types::MQIA]);
104impl_equivalent_type!(types::MQCA, types::MQXA);
105impl_equivalent_type!(types::MQIA, types::MQXA);
106
107/*
108
109MQAI selector constant lookup is complex... thanks to this - no less than 8 different constant sets.
110https://www.ibm.com/docs/en/ibm-mq/latest?topic=reference-mqai-selectors
111
112It would be more efficient to generate one large set as part of the build process, but this will do for now.
113
114*/
115
116impl ConstLookup for crate::mapping::SelectorLookup {
117    fn by_value(&self, value: mq::MQLONG) -> impl Iterator<Item = &str> {
118        let mapping = mapping::MQIA_MAPSTR
119            .by_value(value)
120            .chain(mapping::MQCA_MAPSTR.by_value(value));
121
122        #[cfg(feature = "pcf")]
123        let mapping = mapping
124            .chain(mapping::MQIACF_MAPSTR.by_value(value))
125            .chain(mapping::MQCACF_MAPSTR.by_value(value))
126            .chain(mapping::MQIACH_MAPSTR.by_value(value))
127            .chain(mapping::MQCACH_MAPSTR.by_value(value));
128
129        #[cfg(feature = "mqai")]
130        let mapping = mapping
131            .chain(mapping::MQIASY_MAPSTR.by_value(value))
132            .chain(mapping::MQHA_MAPSTR.by_value(value));
133
134        mapping.chain(FIRST_LAST_MAPSTR.by_value(value))
135    }
136
137    fn by_name(&self, name: &str) -> Option<mq::MQLONG> {
138        let mapping = mapping::MQIA_MAPSTR
139            .by_name(name)
140            .or_else(|| mapping::MQCA_MAPSTR.by_name(name));
141
142        #[cfg(feature = "pcf")]
143        let mapping = mapping
144            .or_else(|| mapping::MQIACF_MAPSTR.by_name(name))
145            .or_else(|| mapping::MQCACF_MAPSTR.by_name(name))
146            .or_else(|| mapping::MQIACH_MAPSTR.by_name(name))
147            .or_else(|| mapping::MQCACH_MAPSTR.by_name(name));
148
149        #[cfg(feature = "mqai")]
150        let mapping = mapping
151            .or_else(|| mapping::MQIASY_MAPSTR.by_name(name))
152            .or_else(|| mapping::MQHA_MAPSTR.by_name(name));
153
154        mapping.or_else(|| FIRST_LAST_MAPSTR.by_name(name))
155    }
156
157    fn all(&self) -> impl Iterator<Item = ConstantItem<'_>> {
158        let mapping = mapping::MQIA_MAPSTR.all().chain(mapping::MQCA_MAPSTR.all());
159
160        #[cfg(feature = "pcf")]
161        let mapping = mapping
162            .chain(mapping::MQIACF_MAPSTR.all())
163            .chain(mapping::MQCACF_MAPSTR.all())
164            .chain(mapping::MQIACH_MAPSTR.all())
165            .chain(mapping::MQCACH_MAPSTR.all());
166
167        #[cfg(feature = "mqai")]
168        let mapping = mapping.chain(mapping::MQIASY_MAPSTR.all()).chain(mapping::MQHA_MAPSTR.all());
169
170        mapping.chain(FIRST_LAST_MAPSTR.all())
171    }
172}
173
174#[cfg(test)]
175#[cfg_attr(coverage_nightly, coverage(off))]
176mod tests {
177    use crate::constants;
178    use crate::types;
179
180    #[test]
181    fn reason_code_display() {
182        assert_eq!(constants::MQRC_Q_MGR_ACTIVE.to_string(), "MQRC_Q_MGR_ACTIVE");
183        assert_eq!(constants::MQRC_NONE.to_string(), "MQRC_NONE");
184        assert_eq!(types::MQRC(-1).to_string(), "-1");
185    }
186
187    #[test]
188    fn ibm_reference_url() {
189        assert_eq!(
190            constants::MQRC_Q_ALREADY_EXISTS.ibm_reference_url("en", None),
191            Some("https://www.ibm.com/docs/en/ibm-mq/latest?topic=codes-2290-08f2-rc2290-mqrc-q-already-exists".to_owned())
192        );
193
194        #[cfg(feature = "pcf")]
195        assert_eq!(
196            types::MQRC::from(constants::MQRCCF_CFH_TYPE_ERROR).ibm_reference_url("en", None),
197            Some("https://www.ibm.com/docs/en/ibm-mq/latest?topic=codes-3001-0bb9-rc3001-mqrccf-cfh-type-error".to_owned())
198        );
199    }
200}