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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
use std::cmp::Ordering;
use std::convert::From;
use std::fmt::{self, Debug, Display};
use windows::Win32::NetworkManagement::Ndis::NET_LUID_LH;

/// Wrapper for the `NET_LUID_LH` struct from the `windows` crate.
///
/// This struct provides a convenient, idiomatic interface for working
/// with network interface Locally Unique Identifiers (LUIDs) in Rust,
/// including implementations of important traits like `PartialEq`, `Eq`,
/// `PartialOrd`, `Ord`, `Debug`, and `Display`.
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct IfLuid(NET_LUID_LH);

impl IfLuid {
    /// Constructs a new `IfLuid` instance from a reference to a `NET_LUID_LH`.
    ///
    /// # Arguments
    ///
    /// * `net_luid_lh` - A reference to a `NET_LUID_LH` value representing the network interface's LUID.
    pub fn new(net_luid_lh: &NET_LUID_LH) -> Self {
        Self(*net_luid_lh)
    }
}

/// Implement the `From` trait for converting a `NET_LUID_LH` value into an `IfLuid` value.
impl From<NET_LUID_LH> for IfLuid {
    /// Converts a `NET_LUID_LH` value into an `IfLuid` value.
    ///
    /// # Arguments
    ///
    /// * `luid`: A `NET_LUID_LH` value to be converted into `IfLuid`.
    ///
    /// # Returns
    ///
    /// * `IfLuid`: The `IfLuid` value representing the given `NET_LUID_LH` value.
    fn from(luid: NET_LUID_LH) -> Self {
        IfLuid(luid)
    }
}

/// Implement the `Into` trait for converting an `IfLuid` value back into a `NET_LUID_LH` value.
impl From<IfLuid> for NET_LUID_LH {
    /// Converts an `IfLuid` value back into a `NET_LUID_LH` value.
    ///
    /// # Arguments
    ///
    /// * `self`: An `IfLuid` value to be converted back into a `NET_LUID_LH` value.
    ///
    /// # Returns
    ///
    /// * `NET_LUID_LH`: The `NET_LUID_LH` value represented by the given `IfLuid` value.
    fn from(val: IfLuid) -> Self {
        val.0
    }
}

/// Implements the conversion from a u64 value to an IfLuid instance.
impl From<u64> for IfLuid {
    /// Converts a u64 value into an IfLuid instance by creating a new NET_LUID_LH structure and
    /// setting its Value field to the input value.
    ///
    /// # Arguments
    ///
    /// * `value` - The u64 value that should be used to set the Value field of the NET_LUID_LH
    ///             structure.
    ///
    /// # Returns
    ///
    /// * An IfLuid instance wrapping the created NET_LUID_LH structure.
    ///
    /// # Examples
    ///
    /// ```
    /// use ndisapi_rs::IfLuid;
    /// // Create two IfLuid instances using u64 values
    /// let value1: u64 = 42;
    /// let if_luid1 = IfLuid::from(value1);
    ///
    /// let value2: u64 = 43;
    /// let if_luid2 = IfLuid::from(value2);
    ///
    /// let value3: u64 = 42;
    /// let if_luid3 = IfLuid::from(value3);
    /// //Compare the two IfLuid instances based on their inner NET_LUID_LH values
    /// assert_ne!(if_luid1, if_luid2);
    /// assert_eq!(if_luid1, if_luid3);
    /// ```
    fn from(value: u64) -> Self {
        // Assuming that the NET_LUID_LH structure has a field `Value` of type u64
        let net_luid_lh = NET_LUID_LH { Value: value };
        IfLuid(net_luid_lh)
    }
}

/// Implementation of `PartialEq` for `IfLuid`.
///
/// Two `IfLuid` instances are considered equal if their `Value` fields are equal.
impl PartialEq for IfLuid {
    fn eq(&self, other: &Self) -> bool {
        unsafe { self.0.Value == other.0.Value }
    }
}

/// Implementation of `Eq` for `IfLuid`.
///
/// This is a marker trait that signals that `IfLuid` fulfills the properties
/// of an equivalence relation for its `PartialEq` implementation.
impl Eq for IfLuid {}

/// Implementation of `PartialOrd` for `IfLuid`.
///
/// `IfLuid` instances are ordered based on their `Value` fields.
impl PartialOrd for IfLuid {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        unsafe { self.0.Value.partial_cmp(&other.0.Value) }
    }
}

/// Implementation of `Ord` for `IfLuid`.
///
/// This implementation provides a total ordering for `IfLuid` instances
/// based on their `Value` fields.
impl Ord for IfLuid {
    fn cmp(&self, other: &Self) -> Ordering {
        unsafe { self.0.Value.cmp(&other.0.Value) }
    }
}

/// Implementation of `Debug` for `IfLuid`.
///
/// The debug representation displays the struct name and the `Value` field
/// of the inner `NET_LUID_LH` union.
impl Debug for IfLuid {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("IfLuid")
            .field("Value", unsafe { &self.0.Value })
            .finish()
    }
}

/// Implementation of `Display` for `IfLuid`.
///
/// The display representation shows the struct name followed by the `Value`
/// field of the inner `NET_LUID_LH` union, enclosed in parentheses.
impl Display for IfLuid {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "IfLuid({})", unsafe { self.0.Value })
    }
}

#[cfg(test)]
mod tests {
    use super::IfLuid;
    use windows::Win32::NetworkManagement::Ndis::NET_LUID_LH;

    #[test]
    fn test_equality() {
        let luid1 = IfLuid(NET_LUID_LH { Value: 42 });
        let luid2 = IfLuid(NET_LUID_LH { Value: 42 });
        let luid3 = IfLuid(NET_LUID_LH { Value: 84 });

        assert_eq!(luid1, luid2);
        assert_ne!(luid1, luid3);
    }

    #[test]
    fn test_ordering() {
        let luid1 = IfLuid(NET_LUID_LH { Value: 42 });
        let luid2 = IfLuid(NET_LUID_LH { Value: 84 });

        assert!(luid1 < luid2);
        assert!(luid2 > luid1);
    }

    #[test]
    fn test_debug() {
        let luid = IfLuid(NET_LUID_LH { Value: 42 });

        let debug_output = format!("{:?}", luid);
        assert_eq!(debug_output, "IfLuid { Value: 42 }");
    }

    #[test]
    fn test_display() {
        let luid = IfLuid(NET_LUID_LH { Value: 42 });

        let display_output = format!("{}", luid);
        assert_eq!(display_output, "IfLuid(42)");
    }
}