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
use proc_macro2::Span;
use syn::visit::Visit;
use syn::ItemStruct;

/// the basic optic, behave as the identity functor
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct __;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Ok<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Err<Optic>(pub Optic);

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Some<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct None<Optic>(pub Optic);

/// behaves as `x.0`, implemented `Lens`
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _0<Optic>(pub Optic);
/// behaves as `x.1`, implemented `Lens`
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _1<Optic>(pub Optic);
/// behaves as `x.2`, implemented `Lens`
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _2<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _3<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _4<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _5<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _6<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _7<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _8<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _9<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _10<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _11<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _12<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _13<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _14<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _15<Optic>(pub Optic);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct _16<Optic>(pub Optic);

/// to traverse all fields of tuples(0~6), implemented `Traversal`
///
/// ```rust
/// assert_eq!((1, 2).view(optics!(_both)), vec![1, 2])
/// ```
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub struct _both<Optic>(pub Optic);

/// to traverse items of collections, implemented `Traversal`
///
/// ```rust
/// assert_eq!(vec![vec![1,2], vec![3,4]].traverse(_mapped._mapped), vec![1, 2, 3, 4])
/// ```
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub struct _mapped<Optic>(pub Optic);

/// to create `Box`, `Rc` or `Arc` pointers, implemented `Review`
///
/// ```rust
/// assert_eq!(Review::review(optics!(_box), 0), Box::new(0));
/// assert_eq!(Review::review(optics!(_box), 0), Rc::new(0));
/// assert_eq!(Review::review(optics!(_box), 0), Arc::new(0));
/// ```
///
/// or to visit the data in `Box`, implemented `Lens`
///
/// ```rust
/// assert_eq!(Box::new(0).view(optic!(_box)), 0);
/// ```
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub struct _box<Optic>(pub Optic);

/// to visit the data in pointers, implemented `LensRef`
///
/// ```rust
/// assert_eq!(Box::new(0).view_ref(optic!(_ref)), &0);
/// assert_eq!(Rc::new(0).view_ref(optic!(_ref)), &0);
///
/// let x = Foo {
///     a: &(1, 2),
///     b: ()
/// };
/// assert_eq!(x.view_ref(optics!(a._ref._1)), &2)
/// ```
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub struct _ref<Optic>(pub Optic);
/// to visit the data in pointers, implemented `LensMut`
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub struct _mut<Optic>(pub Optic);

/// behave as `xs[index]`
///
/// ```rust
/// assert_eq!(vec![1,2,3].view_ref(optics!([1])), &2);
/// assert_eq!(vec![1,2,3].view_ref(optics!([1..])), &[2, 3]);
/// ```
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub struct _ix<I, Optic>(pub Optic, pub I);

include!(concat!(env!("OUT_DIR"), "/optics.rs"));

struct OpticDefinitionsCollector<'a>(&'a mut Vec<syn::Ident>);

impl<'a> Visit<'_> for OpticDefinitionsCollector<'a> {
    fn visit_item_struct(&mut self, item_struct: &ItemStruct) {
        self.0.push(item_struct.ident.clone());
    }
}

/// return all generated optics
pub fn all_optics() -> Vec<syn::Ident> {
    let contents = include_str!(concat!(env!("OUT_DIR"), "/optics.rs"));
    let syntax =
        syn::parse_file(contents).expect(".rs files should contain valid Rust source code.");

    let mut optics = vec![];
    let mut collector = OpticDefinitionsCollector(&mut optics);
    collector.visit_file(&syntax);
    optics.extend(
        vec![
            "Ok", "Err", "Some", "None", "_0", "_1", "_2", "_3", "_4", "_5", "_6", "_7", "_8",
            "_9", "_10", "_11", "_12", "_13", "_14", "_15", "_16",
        ]
        .into_iter()
        .map(|name| syn::Ident::new(name, Span::call_site())),
    );

    optics
}