1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use std::fmt;

use crate::core::target_datalayout as td;

macro_rules! option_field_str {
    ($container:ident, $member:ident) => {
        match &$container.$member {
            Some(v) => v.to_string(),
            None => String::new(),
        }
    };
}

#[derive(PartialEq, PartialOrd, Eq, Ord, Debug)]
pub struct TargetDataLayout {
    pub endian: Option<td::Endian>,
    pub mangling: Option<td::Mangling>,
    pub integer_alignment: Option<td::IntegerAlignment>,
    pub float_alignment: Option<td::FloatAlignment>,
    pub native_integer_width: Option<td::NativeIntegerWidth>,
}

impl fmt::Display for TargetDataLayout {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let layout_strs = vec![
            option_field_str!(self, endian),
            option_field_str!(self, mangling),
            option_field_str!(self, integer_alignment),
            option_field_str!(self, float_alignment),
            option_field_str!(self, native_integer_width),
        ]
        .iter()
        .filter(|st| !st.is_empty())
        .map(|opt_str| opt_str.to_string())
        .collect::<Vec<_>>();

        write!(f, "{}", layout_strs.join("-"))
    }
}

#[cfg(test)]
mod macro_tests {
    #[test]
    fn test_option_field_str_macro() {
        struct Sample {
            foo: Option<i64>,
            bar: Option<i64>,
        }

        let sample = Sample {
            foo: Some(30),
            bar: None,
        };

        assert_eq!("30".to_string(), option_field_str!(sample, foo));

        assert_eq!(String::new(), option_field_str!(sample, bar));
    }
}