bump_scope/
destructure.rs1macro_rules! destructure {
5 (let $ty:ty {
6 $($field:ident $(: $field_alias:ident)?),* $(,)?
7 } = $value:expr) => {
8 let value: $ty = $value;
9 let value = ::core::mem::ManuallyDrop::new(value);
10
11 const _: () = assert!(!$crate::destructure::has_duplicates(&[$(stringify!($field)),*]), "you can't destructure a field twice");
12
13 $(
14 #[allow(unused_unsafe)] let $crate::destructure::or!($($field_alias)? $field) = unsafe { ::core::ptr::read(&value.$field) };
16 )*
17 };
18}
19
20pub(crate) use destructure;
21
22macro_rules! or {
23 ($this:ident $that:ident) => {
24 $this
25 };
26 ($that:ident) => {
27 $that
28 };
29}
30
31pub(crate) use or;
32
33pub(crate) const fn has_duplicates(strings: &[&str]) -> bool {
34 let mut x = 0;
35
36 while x < strings.len() {
37 let mut y = x + 1;
38
39 while y < strings.len() {
40 if str_eq(strings[x], strings[y]) {
41 return true;
42 }
43
44 y += 1;
45 }
46
47 x += 1;
48 }
49
50 false
51}
52
53const fn str_eq(a: &str, b: &str) -> bool {
54 let a = a.as_bytes();
55 let b = b.as_bytes();
56
57 if a.len() != b.len() {
58 return false;
59 }
60
61 let mut i = 0;
62
63 while i < a.len() {
64 if a[i] != b[i] {
65 return false;
66 }
67
68 i += 1;
69 }
70
71 true
72}
73
74#[cfg(test)]
75mod tests {
76 use std::string::String;
77
78 #[test]
79 fn example() {
80 pub struct Foo {
81 bar: String,
82 baz: String,
83 }
84
85 impl Drop for Foo {
86 fn drop(&mut self) {
87 unreachable!()
88 }
89 }
90
91 let foo = Foo {
92 bar: "bar".into(),
93 baz: "baz".into(),
94 };
95
96 destructure!(let Foo { bar: qux, baz } = foo);
100
101 assert_eq!(qux, "bar");
102 assert_eq!(baz, "baz");
103 }
104}