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}