field_ref/lib.rs
1//!
2//! GetField reference (like a member pointer to non-static data field in C++) for Rust
3//!
4//! # Examples
5//!
6//! Subfield of type `U` which is contained by `T` can be obtained via `FieldRef<T, U>`.
7//!
8//! ```
9//! use field_ref::{GetField, GetFieldMut, field_ref_of};
10//!
11//! struct Foo(u32, u32, f64);
12//! struct Bar {
13//! foo: Foo,
14//! x: u32,
15//! }
16//!
17//! # fn main() {
18//! let fr1 = field_ref_of!(Bar => x);
19//! let fr2 = field_ref_of!(Bar => foo);
20//! let fr3 = field_ref_of!(Foo => 1);
21//! let fr4 = field_ref_of!(Bar => foo => 0);
22//!
23//! let mut bar = Bar { foo: Foo(10, 20, 0.5), x: 30 };
24//!
25//! assert_eq!(bar.get_field(fr1), &30);
26//! assert_eq!(fr1.get(&bar), &30);
27//!
28//! *bar.get_field_mut(fr1) = 100;
29//! assert_eq!(bar.x, 100);
30//!
31//! *fr1.get_mut(&mut bar) = 200;
32//! assert_eq!(bar.x, 200);
33//!
34//! assert_eq!(bar.get_field(fr2.chain(fr3)), &20);
35//! assert_eq!(bar.get_field(fr4), &10);
36//! # }
37//! ```
38//!
39//! Enum field of type `T` can be obtain as `Option<&T>` via `OptionFieldRef`.
40//! Other field such as struct field of type `T` can also be obtain as `Option<&T>` via `OptionFieldRef`.
41//!
42//! ```
43//! use field_ref::{GetField, GetFieldMut, OptionFieldRef, opt_field_ref_of};
44//!
45//! struct Foo {
46//! x: i32,
47//! y: f64,
48//! }
49//!
50//! enum E1 {
51//! A(i32),
52//! B(i32, Foo),
53//! }
54//!
55//! enum E2 {
56//! X(E1),
57//! Y,
58//! }
59//!
60//! # fn main() {
61//! let fr1 = opt_field_ref_of!(E1::A{0});
62//! let fr2 = opt_field_ref_of!(E2::X{0} & E1::B{1} => y);
63//! let fr3 = opt_field_ref_of!(Foo => x);
64//!
65//! let e1_1 = E1::A(10);
66//! let e1_2 = E1::B(20, Foo{ x: 25, y: 2.5 });
67//! let e2_1 = E2::X(E1::B(10, Foo{ x: 30, y: 3.5 }));
68//! let e2_2 = E2::Y;
69//!
70//! let mut foo = Foo{ x: 40, y: 4.5 };
71//!
72//! assert_eq!(e1_1.try_get_field(fr1), Some(&10));
73//! assert_eq!(e1_2.try_get_field(fr1), None);
74//!
75//! assert_eq!(e2_1.try_get_field(fr2), Some(&3.5));
76//! assert_eq!(e2_2.try_get_field(fr2), None);
77//!
78//! assert_eq!(foo.try_get_field(fr3), Some(&40));
79//! *foo.try_get_field_mut(fr3).unwrap() = 50;
80//! assert_eq!(foo.x, 50)
81//! # }
82//! ```
83//!
84
85use std::marker::PhantomData;
86use std::cmp::{Eq, PartialEq, Ord, PartialOrd, Ordering};
87
88
89///
90/// A reference to field of type `U` (recursively) contained by an object of type `T`.
91///
92pub struct FieldRef<T, U> {
93 offset: usize,
94 phantom: PhantomData<(T, U)>,
95}
96
97impl<T, U> FieldRef<T, U> {
98 /// Creates a new `FieldRef` with offset bytes from the first byte of an object of type `T`.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// use field_ref::FieldRef;
104 ///
105 /// #[repr(C)]
106 /// struct Foo(u32, u32);
107 ///
108 /// # fn main() {
109 /// // references Foo.1
110 /// let fr = unsafe { FieldRef::<Foo, u32>::from_offset(4) };
111 /// let foo = Foo(10, 20);
112 /// assert_eq!(fr.get(&foo), &20);
113 /// # }
114 /// ```
115 pub unsafe fn from_offset(offset: usize) -> Self {
116 Self { offset, phantom: PhantomData }
117 }
118
119 /// Creates a new `FieldRef` from a reference to concrete object of type `T` and a reference to concrete field of type `U`.
120 ///
121 /// # Examples
122 ///
123 /// ```
124 /// use field_ref::FieldRef;
125 ///
126 /// struct Foo(u32, u32, f64);
127 ///
128 /// # fn main() {
129 /// let foo1 = Foo(10, 20, 0.5);
130 /// let foo2 = Foo(30, 40, 1.5);
131 /// let fr = unsafe { FieldRef::from_pointers(&foo1, &foo1.1) };
132 /// assert_eq!(fr.get(&foo2), &40);
133 /// # }
134 /// ```
135 pub unsafe fn from_pointers(obj: *const T, field: *const U) -> Self {
136 Self::from_offset(field as usize - obj as usize)
137 }
138
139 /// Creates a new `FieldRef` from a pointer to concrete object of type `T` and a pointer to concrete field of type `U`.
140 ///
141 /// # Examples
142 ///
143 /// ```
144 /// use field_ref::FieldRef;
145 ///
146 /// struct Foo(u32, u32, f64);
147 ///
148 /// # fn main() {
149 /// let foo1 = Foo(10, 20, 0.5);
150 /// let foo2 = Foo(30, 40, 1.5);
151 /// let fr = unsafe { FieldRef::from_references(&foo1, &foo1.1) };
152 /// assert_eq!(fr.get(&foo2), &40);
153 /// # }
154 /// ```
155 pub unsafe fn from_references(obj: &T, field: &U) -> Self {
156 Self::from_pointers(obj, field)
157 }
158
159 /// Get the offset of target field.
160 pub fn offset(&self) -> usize {
161 self.offset
162 }
163
164 /// Get a reference of value in an object to which `FieldRef` refers.
165 ///
166 /// # Examples
167 ///
168 /// ```
169 /// use field_ref::field_ref_of;
170 ///
171 /// struct Foo(u32, u32, f64);
172 ///
173 /// # fn main() {
174 /// let fr = field_ref_of!(Foo => 1);
175 /// let foo = Foo(10, 20, 0.5);
176 /// assert_eq!(fr.get(&foo), &20);
177 /// # }
178 /// ```
179 pub fn get<'a, 'b>(&'a self, obj: &'b T) -> &'b U {
180 let addr = obj as *const _ as usize + self.offset;
181 unsafe { &*(addr as *const U) }
182 }
183
184 #[deprecated(note = "Use `get` instead")]
185 pub fn get_ref<'a, 'b>(&'a self, obj: &'b T) -> &'b U {
186 self.get(obj)
187 }
188
189 /// Get a mutable reference of value in an object to which `FieldRef` refers.
190 ///
191 /// # Examples
192 ///
193 /// ```
194 /// use field_ref::field_ref_of;
195 ///
196 /// struct Foo(u32, u32, f64);
197 ///
198 /// # fn main() {
199 /// let fr = field_ref_of!(Foo => 1);
200 /// let mut foo = Foo(10, 20, 0.5);
201 /// *fr.get_mut(&mut foo) = 30;
202 /// assert_eq!(foo.1, 30);
203 /// # }
204 /// ```
205 pub fn get_mut<'a, 'b>(&'a self, obj: &'b mut T) -> &'b mut U {
206 let addr = obj as *mut _ as usize + self.offset;
207 unsafe { &mut *(addr as *mut U) }
208 }
209
210 /// Chains two field references.
211 ///
212 /// # Examples
213 ///
214 /// ```
215 /// use field_ref::field_ref_of;
216 ///
217 /// struct Foo(u32, u32, f64);
218 /// struct Bar {
219 /// foo: Foo,
220 /// x: u32,
221 /// }
222 ///
223 /// # fn main() {
224 /// let fr1 = field_ref_of!(Bar => foo);
225 /// let fr2 = field_ref_of!(Foo => 1);
226 /// let bar = Bar { foo: Foo(10, 20, 0.5), x: 30 };
227 /// assert_eq!(fr1.chain(fr2).get(&bar), &20);
228 /// # }
229 /// ```
230 pub fn chain<V>(&self, fr: FieldRef<U, V>) -> FieldRef<T, V> {
231 unsafe { FieldRef::<T, V>::from_offset(self.offset + fr.offset) }
232 }
233
234 /// Convert `FieldRef<T, U>` into an instance of trait `OptionFieldRef<'x, Input = T, Output = U>`.
235 pub fn as_opt_field_ref(&self) -> FieldRefAsOptionFieldRef<T, U> {
236 FieldRefAsOptionFieldRef(*self)
237 }
238}
239
240impl<T, U> Clone for FieldRef<T, U> {
241 fn clone(&self) -> Self {
242 Self { offset: self.offset, phantom: PhantomData }
243 }
244}
245
246impl<T, U> Copy for FieldRef<T, U> {}
247
248impl<T, U> std::fmt::Debug for FieldRef<T, U> {
249 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
250 write!(f, "FieldRef {{ offset: {} }}", self.offset)
251 }
252}
253
254impl<T, U> PartialEq for FieldRef<T, U> {
255 fn eq(&self, other: &Self) -> bool {
256 self.offset == other.offset
257 }
258}
259
260impl<T, U> Eq for FieldRef<T, U> {}
261
262impl<T, U> PartialOrd for FieldRef<T, U> {
263 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
264 self.offset.partial_cmp(&other.offset)
265 }
266}
267
268impl<T, U> Ord for FieldRef<T, U> {
269 fn cmp(&self, other: &Self) -> Ordering {
270 self.offset.cmp(&other.offset)
271 }
272}
273
274
275///
276/// A reference to field of type `Input` (recursively) contained by an object of type `Output`
277/// and that may fail dereference.
278///
279pub trait OptionFieldRef<'x> where Self: Copy {
280 type Input;
281 type Output;
282
283 /// Get a reference of value in an object to which `OptionFieldRef` refers.
284 ///
285 /// # Examples
286 ///
287 /// ```
288 /// use field_ref::{OptionFieldRef, opt_field_ref_of};
289 ///
290 /// enum E {
291 /// A(i32, char),
292 /// B(i32)
293 /// }
294 ///
295 /// # fn main() {
296 /// let fr = opt_field_ref_of!(E::A{0});
297 /// let e1 = E::A(10, 'a');
298 /// let e2 = E::B(20);
299 /// assert_eq!(fr.get(&e1), Some(&10));
300 /// assert_eq!(fr.get(&e2), None);
301 /// # }
302 /// ```
303 fn get<'a>(&'a self, obj: &'x Self::Input) -> Option<&'x Self::Output>;
304
305 /// Get a mutable reference of value in an object to which `OptionFieldRef` refers.
306 ///
307 /// # Examples
308 ///
309 /// ```
310 /// use field_ref::{OptionFieldRef, opt_field_ref_of};
311 ///
312 /// #[derive(Debug, Eq, PartialEq)]
313 /// enum E {
314 /// A(i32, char),
315 /// B(i32)
316 /// }
317 ///
318 /// # fn main() {
319 /// let fr = opt_field_ref_of!(E::B{0});
320 /// let mut e = E::B(10);
321 /// *fr.get_mut(&mut e).unwrap() = 20;
322 /// assert_eq!(e, E::B(20));
323 /// # }
324 /// ```
325 fn get_mut<'a>(&'a self, obj: &'x mut Self::Input) -> Option<&'x mut Self::Output>;
326
327 /// Chains two field references.
328 ///
329 /// # Examples
330 ///
331 /// ```
332 /// use field_ref::{OptionFieldRef, opt_field_ref_of};
333 ///
334 /// enum E1 {
335 /// A(i32),
336 /// B(i32, char),
337 /// }
338 ///
339 /// enum E2 {
340 /// X(E1),
341 /// Y,
342 /// }
343 ///
344 /// # fn main() {
345 /// let fr1 = opt_field_ref_of!(E2::X{0});
346 /// let fr2 = opt_field_ref_of!(E1::A{0});
347 /// let e2 = E2::X(E1::A(10));
348 /// assert_eq!(fr1.chain(fr2).get(&e2), Some(&10));
349 /// # }
350 /// ```
351 fn chain<FR, R: 'x>(&self, fr: FR) -> OptionFieldRefChain<Self, FR>
352 where
353 FR: OptionFieldRef<'x, Input = Self::Output, Output = R> + Copy
354 {
355 OptionFieldRefChain(*self, fr)
356 }
357}
358
359///
360/// A `OptionFieldRef` references a field within an enum constant.
361///
362pub struct EnumFieldRef<E, T> {
363 extractor: fn(&E) -> Option<&T>,
364 mut_extractor: fn(&mut E) -> Option<&mut T>,
365}
366
367impl<E, T> EnumFieldRef<E, T> {
368 /// Creates a new `EnumFieldRef` from a field extracting function and a mutable field extracting function.
369 pub fn new(extractor: fn(&E) -> Option<&T>, mut_extractor: fn(&mut E) -> Option<&mut T>) -> Self {
370 Self { extractor, mut_extractor }
371 }
372}
373
374impl<'x, E: 'x, T: 'x> OptionFieldRef<'x> for EnumFieldRef<E, T> {
375 type Input = E;
376 type Output = T;
377
378 fn get<'a>(&'a self, e: &'x Self::Input) -> Option<&'x Self::Output> {
379 (self.extractor)(e)
380 }
381
382 fn get_mut<'a>(&'a self, e: &'x mut Self::Input) -> Option<&'x mut Self::Output> {
383 (self.mut_extractor)(e)
384 }
385}
386
387impl<E, T> Clone for EnumFieldRef<E, T> {
388 fn clone(&self) -> Self {
389 Self { extractor: self.extractor, mut_extractor: self.mut_extractor }
390 }
391}
392
393impl<E, T> Copy for EnumFieldRef<E, T> {}
394
395///
396/// A `OptionFieldRef` which chains two `OptionFieldRef`s.
397///
398pub struct OptionFieldRefChain<FR1: Copy, FR2: Copy>(FR1, FR2);
399
400impl<'x, T: 'x, U: 'x, V: 'x, FR1, FR2> OptionFieldRef<'x> for OptionFieldRefChain<FR1, FR2> where
401 FR1: OptionFieldRef<'x, Input = T, Output = U>,
402 FR2: OptionFieldRef<'x, Input = U, Output = V>,
403{
404 type Input = T;
405 type Output = V;
406
407 fn get<'a>(&'a self, obj: &'x Self::Input) -> Option<&'x Self::Output> {
408 self.0.get(obj).and_then(|y| self.1.get(y))
409 }
410
411 fn get_mut<'a>(&'a self, obj: &'x mut Self::Input) -> Option<&'x mut Self::Output> {
412 self.0.get_mut(obj).and_then(|y| self.1.get_mut(y))
413 }
414}
415
416impl <FR1: Copy, FR2: Copy> Clone for OptionFieldRefChain<FR1, FR2> {
417 fn clone(&self) -> Self {
418 OptionFieldRefChain(self.0, self.1)
419 }
420}
421
422impl <FR1: Copy, FR2: Copy> Copy for OptionFieldRefChain<FR1, FR2> {}
423
424///
425/// A `OptionFieldRef` which converted from A `FieldRef`.
426///
427pub struct FieldRefAsOptionFieldRef<T, U>(FieldRef<T, U>);
428
429impl<'x, T, U> OptionFieldRef<'x> for FieldRefAsOptionFieldRef<T, U> {
430 type Input = T;
431 type Output = U;
432
433 fn get<'a>(&'a self, obj: &'x Self::Input) -> Option<&'x Self::Output> {
434 Some(self.0.get(obj))
435 }
436
437 fn get_mut<'a>(&'a self, obj: &'x mut Self::Input) -> Option<&'x mut Self::Output> {
438 Some(self.0.get_mut(obj))
439 }
440}
441
442impl<T, U> Clone for FieldRefAsOptionFieldRef<T, U> {
443 fn clone(&self) -> Self {
444 FieldRefAsOptionFieldRef(self.0)
445 }
446}
447
448impl<T, U> Copy for FieldRefAsOptionFieldRef<T, U> {}
449
450///
451/// A trait to obtain a value to which `FieldRef` references via description like `obj.get_field(field_ref)`.
452///
453pub trait GetField where Self: Sized {
454 /// # Examples
455 ///
456 /// ```
457 /// use field_ref::{GetField, field_ref_of};
458 ///
459 /// struct Foo(u32, u32, f64);
460 ///
461 /// # fn main() {
462 /// let fr = field_ref_of!(Foo => 1);
463 /// let foo = Foo(10, 20, 0.5);
464 /// assert_eq!(foo.get_field(fr), &20);
465 /// # }
466 /// ```
467 fn get_field<T>(&self, fr: FieldRef<Self, T>) -> &T;
468
469 fn try_get_field<'x, FR, T>(&'x self, fr: FR) -> Option<&'x T>
470 where
471 FR: OptionFieldRef<'x, Input = Self, Output = T>;
472}
473
474///
475/// Creates a new `FieldRef` from basic type and fields which are (recursively) contained by that type.
476///
477/// # Examples
478///
479/// ```
480/// use field_ref::{FieldRef, field_ref_of};
481///
482/// struct Foo(u32, u32);
483///
484/// # fn main() {
485/// // references Foo.1
486/// let fr = field_ref_of!(Foo => 1);
487/// let foo = Foo(10, 20);
488/// assert_eq!(fr.get(&foo), &20);
489/// # }
490/// ```
491#[macro_export]
492macro_rules! field_ref_of {
493 ($t:ty $(=> $f:tt)+) => {
494 unsafe {
495 let base = ::std::ptr::null() as *const $t;
496 $crate::FieldRef::from_pointers(base, &(*base)$(.$f)+)
497 }
498 };
499}
500
501///
502/// A trait to obtain a mutable value to which `FieldRef` references via description like `obj.get_field_mut(field_ref)`.
503///
504pub trait GetFieldMut where Self: Sized {
505 /// # Examples
506 ///
507 /// ```
508 /// use field_ref::{GetFieldMut, field_ref_of};
509 ///
510 /// struct Foo(u32, u32, f64);
511 ///
512 /// # fn main() {
513 /// let fr = field_ref_of!(Foo => 1);
514 /// let mut foo = Foo(10, 20, 0.5);
515 /// *foo.get_field_mut(fr) = 30;
516 /// assert_eq!(foo.1, 30);
517 /// # }
518 /// ```
519 fn get_field_mut<T>(&mut self, fr: FieldRef<Self, T>) -> &mut T;
520
521 fn try_get_field_mut<'x, FR, T>(&'x mut self, fr: FR) -> Option<&'x mut T>
522 where
523 FR: OptionFieldRef<'x, Input = Self, Output = T>;
524}
525
526impl<S: Sized> GetField for S {
527 fn get_field<T>(&self, fr: FieldRef<Self, T>) -> &T {
528 fr.get(self)
529 }
530
531 fn try_get_field<'x, FR, T>(&'x self, fr: FR) -> Option<&'x T>
532 where
533 FR: OptionFieldRef<'x, Input = Self, Output = T>
534 {
535 fr.get(self)
536 }
537}
538
539impl<S: Sized> GetFieldMut for S {
540 fn get_field_mut<T>(&mut self, fr: FieldRef<Self, T>) -> &mut T {
541 fr.get_mut(self)
542 }
543
544 fn try_get_field_mut<'x, FR, T>(&'x mut self, fr: FR) -> Option<&'x mut T>
545 where
546 FR: OptionFieldRef<'x, Input = Self, Output = T>
547 {
548 fr.get_mut(self)
549 }
550}
551
552/// Creates a new instance of `OptionFieldRef` from basic type (enum constansts, structs or tuples) and these fields.
553///
554/// # Examples
555///
556/// ```
557/// use field_ref::{GetField, GetFieldMut, OptionFieldRef, opt_field_ref_of};
558///
559/// struct Foo {
560/// x: i32,
561/// y: f64,
562/// }
563///
564/// enum E1 {
565/// A(i32),
566/// B(i32, Foo),
567/// }
568///
569/// enum E2 {
570/// X(E1),
571/// Y,
572/// }
573///
574/// # fn main() {
575/// let fr1 = opt_field_ref_of!(E1::A{0});
576/// let fr2 = opt_field_ref_of!(E2::X{0} & E1::B{1} => y);
577/// let fr3 = opt_field_ref_of!(Foo => x);
578///
579/// let e1_1 = E1::A(10);
580/// let e1_2 = E1::B(20, Foo{ x: 25, y: 2.5 });
581/// let e2_1 = E2::X(E1::B(10, Foo{ x: 30, y: 3.5 }));
582/// let e2_2 = E2::Y;
583///
584/// let mut foo = Foo{ x: 40, y: 4.5 };
585///
586/// assert_eq!(e1_1.try_get_field(fr1), Some(&10));
587/// assert_eq!(e1_2.try_get_field(fr1), None);
588///
589/// assert_eq!(e2_1.try_get_field(fr2), Some(&3.5));
590/// assert_eq!(e2_2.try_get_field(fr2), None);
591///
592/// assert_eq!(foo.try_get_field(fr3), Some(&40));
593/// *foo.try_get_field_mut(fr3).unwrap() = 50;
594/// assert_eq!(foo.x, 50)
595/// # }
596/// ```
597#[macro_export]
598macro_rules! opt_field_ref_of {
599 ($e:path { $f:tt } $(=> $fs:tt)*) => {
600 $crate::EnumFieldRef::new(
601 $crate::enum_field_extractor!($e => $f $(=> $fs)*),
602 $crate::enum_field_extractor!($e => $f $(=> $fs)*, mut)
603 )
604 };
605
606 ($e:path { $f:tt } $(=> $fs:tt)* & $($tts:tt)+) => {
607 $crate::EnumFieldRef::new(
608 $crate::enum_field_extractor!($e => $f $(=> $fs)*),
609 $crate::enum_field_extractor!($e => $f $(=> $fs)*, mut)
610 )
611 .chain($crate::opt_field_ref_of!($($tts)+))
612 };
613
614 ($t:ty $(=> $f:tt)+) => {
615 $crate::field_ref_of!($t $(=> $f)+).as_opt_field_ref()
616 };
617
618 ($t:ty $(=> $f:tt)+ & $($tts:tt)+) => {
619 $crate::field_ref_of!($t $(=> $f)+).as_opt_field_ref()
620 .chain($crate::opt_field_ref_of!($($tts)+))
621 };
622}
623
624#[doc(hidden)]
625#[macro_export]
626macro_rules! enum_field_extractor {
627 ($e:path => $f:tt $(=> $fs:tt)* $(, $mut:tt)*) => {
628 #[allow(non_shorthand_field_patterns)]
629 |e| if let &$($mut)* $e { $f: ref $($mut)* x, .. } = e {
630 Some(&$($mut)*(*x) $(.$fs)*)
631 } else {
632 None
633 }
634 };
635}
636
637#[cfg(test)]
638mod tests {
639 use super::*;
640
641 #[repr(C)] // to guarantee the result of Ord test
642 struct Foo(u32, u32);
643
644 struct Bar {
645 foo: Foo,
646 x: u32,
647 }
648
649 #[test]
650 fn basic_test() {
651 let mut foo = Foo(10, 20);
652 let fr1 = field_ref_of!(Foo => 0);
653 let fr2 = field_ref_of!(Foo => 1);
654
655 assert_eq!(fr1.get(&foo), &10);
656 assert_eq!(foo.get_field(fr2), &20);
657
658 *fr2.get_mut(&mut foo) = 30;
659 *foo.get_field_mut(fr1) = 40;
660 assert_eq!(foo.0, 40);
661 assert_eq!(foo.1, 30);
662 }
663
664 #[test]
665 fn multi_level_test() {
666 let bar = Bar{ foo: Foo(10, 20), x: 30 };
667 let fr1 = field_ref_of!(Bar => foo => 1);
668 let fr2 = field_ref_of!(Bar => foo);
669 let fr3 = field_ref_of!(Foo => 1);
670 let fr4 = field_ref_of!(Bar => x);
671
672 assert_eq!(bar.get_field(fr1), &20);
673 assert_eq!(bar.get_field(fr2.chain(fr3)), &20);
674 assert_eq!(bar.get_field(fr4), &30);
675 }
676
677 #[test]
678 fn debug_test() {
679 let fr = unsafe { FieldRef::<Foo, u32>::from_offset(100) };
680 assert_eq!(format!("{:?}", fr), "FieldRef { offset: 100 }");
681 }
682
683 #[test]
684 fn eq_test() {
685 let fr1 = field_ref_of!(Bar => foo => 1);
686 let fr2 = field_ref_of!(Bar => foo);
687 let fr3 = field_ref_of!(Foo => 1);
688 let fr4 = field_ref_of!(Bar => x);
689
690 assert!(fr1 != fr4);
691 assert!(fr1 == fr2.chain(fr3));
692 }
693
694 #[test]
695 fn ord_test() {
696 let fr1 = field_ref_of!(Bar => foo => 0);
697 let fr2 = field_ref_of!(Bar => foo => 1);
698 let fr3 = field_ref_of!(Bar => foo);
699 let fr4 = field_ref_of!(Foo => 1);
700
701 assert_eq!(fr1.cmp(&fr2), Ordering::Less);
702 assert_eq!(fr2.cmp(&fr1), Ordering::Greater);
703 assert_eq!(fr2.cmp(&fr3.chain(fr4)), Ordering::Equal);
704 }
705
706 #[derive(Debug, Eq, PartialEq)]
707 enum E {
708 A(u32, u32),
709 B{ x: u32, y: u32 },
710 C,
711 }
712
713 mod sub {
714 #[allow(dead_code)]
715 pub enum E2 {
716 X(u32),
717 Y,
718 }
719 }
720
721 #[test]
722 fn enum_field_basic_test() {
723 let fr1 = opt_field_ref_of!(E::A{1});
724 let fr2 = opt_field_ref_of!(E::B{x});
725 let mut e1 = E::A(10, 20);
726 let e2 = E::B{ x: 30, y: 40 };
727 let e3 = E::C;
728
729 assert_eq!(fr1.get(&e1), Some(&20));
730 assert_eq!(fr1.get(&e2), None);
731 assert_eq!(fr1.get(&e3), None);
732 *fr1.get_mut(&mut e1).unwrap() = 100;
733 assert_eq!(e1, E::A(10, 100));
734
735 assert_eq!(fr2.get(&e2), Some(&30));
736 }
737
738 #[test]
739 fn enum_field_enum_with_path_test() {
740 let fr1 = opt_field_ref_of!(sub::E2::X{0});
741 let e1 = sub::E2::X(10);
742
743 assert_eq!(fr1.get(&e1), Some(&10));
744 }
745}