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
//! Module that holds procedural macros for Frunk
//!
//!
//! # Examples
//!
//! ```
//! #[macro_use] extern crate frunk;
//! #[macro_use] extern crate frunk_core;
//! # extern crate frunk_proc_macros;
//! # use frunk_proc_macros::path;
//! # fn main() {
//! #[derive(LabelledGeneric)]
//! struct Dog<'a> {
//!     name: &'a str,
//!     dimensions: Dimensions,
//! }
//!
//! #[derive(LabelledGeneric)]
//! struct Cat<'a> {
//!     name: &'a str,
//!     dimensions: Dimensions,
//! }
//!
//! #[derive(LabelledGeneric)]
//! struct Dimensions {
//!     height: usize,
//!     width: usize,
//!     unit: SizeUnit,
//! }
//!
//! #[derive(Debug, Eq, PartialEq)]
//! enum SizeUnit {
//!     Cm,
//!     Inch,
//! }
//!
//! let mut dog = Dog {
//!     name: "Joe",
//!     dimensions: Dimensions {
//!         height: 10,
//!         width: 5,
//!         unit: SizeUnit::Inch,
//!     },
//! };
//!
//! let cat = Cat {
//!     name: "Schmoe",
//!     dimensions: Dimensions {
//!         height: 7,
//!         width: 3,
//!         unit: SizeUnit::Cm,
//!     },
//! };
//!
//! // generic, re-usable paths
//! let height_lens = path!(dimensions.height);
//! let unit_lens = path!(dimensions.unit);
//!
//! assert_eq!(*height_lens.get(&dog), 10);
//! assert_eq!(*height_lens.get(&cat), 7);
//! assert_eq!(*unit_lens.get(&dog), SizeUnit::Inch);
//! assert_eq!(*unit_lens.get(&cat), SizeUnit::Cm);
//!
//! // modify
//! *height_lens.get(&mut dog) = 13;
//! assert_eq!(*height_lens.get(&dog), 13);
//! # }
//! ```

extern crate frunk_core;
extern crate frunk_proc_macros_impl;
extern crate proc_macro_hack;

use proc_macro_hack::proc_macro_hack;

/// Add one to an expression.
#[proc_macro_hack]
pub use frunk_proc_macros_impl::path;

#[cfg(test)]
#[macro_use]
extern crate frunk;

#[cfg(test)]
mod tests {

    #[test]
    fn test_path() {
        #[derive(LabelledGeneric)]
        struct Dog<'a> {
            name: &'a str,
            dimensions: Dimensions,
        }

        #[derive(LabelledGeneric)]
        struct Cat<'a> {
            name: &'a str,
            dimensions: Dimensions,
        }

        #[derive(LabelledGeneric)]
        struct Dimensions {
            height: usize,
            width: usize,
            unit: SizeUnit,
        }

        #[derive(Debug, Eq, PartialEq)]
        enum SizeUnit {
            Cm,
            Inch,
        }

        let mut dog = Dog {
            name: "Joe",
            dimensions: Dimensions {
                height: 10,
                width: 5,
                unit: SizeUnit::Inch,
            },
        };

        let cat = Cat {
            name: "Schmoe",
            dimensions: Dimensions {
                height: 7,
                width: 3,
                unit: SizeUnit::Cm,
            },
        };

        // generic, re-usable, compsable paths
        let dimensions_lens = path!(dimensions);
        let height_lens = dimensions_lens + path!(height); // compose multiple
        let unit_lens = path!(dimensions.unit); // dot syntax to just do the whole thing at once

        assert_eq!(*height_lens.get(&dog), 10);
        assert_eq!(*height_lens.get(&cat), 7);
        assert_eq!(*unit_lens.get(&dog), SizeUnit::Inch);
        assert_eq!(*unit_lens.get(&cat), SizeUnit::Cm);

        // modify
        *height_lens.get(&mut dog) = 13;
        assert_eq!(*height_lens.get(&dog), 13);
    }
}