File: README.md

package info (click to toggle)
rust-derive-getters 0.5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 248 kB
  • sloc: makefile: 2
file content (262 lines) | stat: -rw-r--r-- 7,937 bytes parent folder | download
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# Derive Getters

Simple `Getters` derive macro for generating field getter methods on a named struct. Included is an additional derive, `Dissolve`, that consumes the struct returning a tuple of all fields in the order they were declared. Dissolve can also be derived for tuple structs.  Any doc comments on the target struct fields are replicated for the corresponding getters. If no comment is present one shall be generated.

The need for the `Getters` macro came about when I was making various data structures for JSON to deserialize into. These data structures had many fields in them to access and they weren't going to change once created. One could use `pub` everywhere but that would enable mutating the fields which is what this derive aims to avoid.

Getters will be generated according to [convention](https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis). This means that the generated methods will reside within the struct namespace.

With regards to `Dissolve`, sometimes during conversion a structure must be consumed. One easy way to do this is to return a tuple of all the structs fields. Thus `Dissolve` can be considered a 'get (move) everything' method call.

## What this crate won't do
There are no mutable getters and it's not planned. There are no setters either nor will there ever be.

## Rust Docs
[Documentation is here.](https://docs.rs/derive-getters)

## Installation

Add to your `Cargo.toml`:
```toml
[dependencies]
derive-getters = "0.5.0"
```

Then import the `Getters` or `Dissolve` macro in whichever module it's needed (assuming 2018 edition).
```rust
use derive_getters::{Getters, Dissolve};

```
Otherwise just import at crate root.
```rust
#[macro_use]
extern crate derive_getters;
```

## Features

* `auto_copy_getters` - enable to automatically generate copy getters for primitive types (return by value instead of by reference).

## Usage

When you have a struct you want to automatically derive getters for... Just add the derive at the top like so;
```rust
#[derive(Getters)]
pub struct MyCheesyStruct {
    x: i64,
    y: i64,
}
```

A new impl will be produced for `MyCheesyStruct`.
```rust
/// Auto-generated by `derive_getters::Getters`.
impl MyCheesyStruct {
    /// Get field `x` from instance of `MyCheesyStruct`.
    pub fn x(&self) -> &i64 {
        &self.x
    }

    /// Get field `y` from instance of `MyCheesyStruct`.
    pub fn y(&self) -> &i64 {
        &self.y
    }
}
```

You can also derive "copy getters" that return by value instead of by reference:
```rust
#[derive(Getters)]
pub struct MyCheesyStruct {
    #[getter(copy)]
    x: i64,
    #[getter(copy)]
    y: i64,
}
```

This will generate the following impl for `MyCheesyStruct`.
```rust
/// Auto-generated by `derive_getters::Getters`.
impl MyCheesyStruct {
    /// Get field `x` from instance of `MyCheesyStruct`.
    pub fn x(&self) -> i64 {
        self.x
    }

    /// Get field `y` from instance of `MyCheesyStruct`.
    pub fn y(&self) -> i64 {
        self.y
    }
}
```

If you want to automatically generate copy getters for primitive types, you can enable the `auto_copy_getters` feature.

It is recommended to enable `auto_copy_getters` because it makes your code faster (no need to dereference a pointer). The Rust reference [recommends implementing the `Copy` trait](https://doc.rust-lang.org/std/marker/trait.Copy.html#when-should-my-type-be-copy). 

This crate can also handle structs with simple generic parameters and lifetime annotations. Check [docs](https://docs.rs/derive-getters) for further details.
```rust
#[derive(Getters)]
pub struct StructWithGeneric<'a, T> {
    concrete: f64,
    generic: T,
    text: &'a str,
}
```

With `Dissolve`, use it like so;
```rust
#[derive(Dissolve)]
pub struct Solid {
    a: u64,
    b: f64,
    c: i64,
}
```

An impl will be produced for `Solid` like so;
```rust
/// Auto-generated by `derive_getters::Dissolve`.
impl Solid {
    /// Dissolve `Solid` into a tuple consisting of its fields in order of declaration.
    pub fn dissolve(self) -> (u64, f64, i64) {
      (self.a, self.b, self.c)
    }
}
```

### Attributes
`Getters` attributes:
* `#[getter(skip)]` on the field to skip generating a getter for it.
* `#[getter(copy)]` on the field to return a value by copy instead of by reference (note: the value must implement the `Copy` trait).
* `#[getter(rename = "name")]` on the field to change the getter name to "name".

`Dissolve` attributes:
* `#[dissolve(rename = "name")]` on the struct to change the name of the dissolve function to "name".

## Comment Preservation

Doc comments on fields shall be copied over onto their respective getters. If there is no comment for the field then one shall be generated.

For example, this struct;
```rust
#[derive(Getters, Dissolve)]
#[dissolve(rename = "melt")]
struct Funky<'a, T> {
    number: i64,

    /// This is commented.
    commented: T,

    /// This comment is over
    /// many lines.
    /// Here's another line.
    #[getter(rename = "floating")]
    many_line: f32,

    /**
     * This is one of those
     * pesky multi-line
     * comments.
     */
    multi_line: &'a str,

    /// We don't care for this field.
    #[getter(skip)]
    ignore_me: u16,

    #[doc = r" A doc comment"]
    one_comment: u64,

    #[doc = include_str!("../COMMENTS.md")]
    incl_comment: u64,

    #[doc(hidden)]
    /// This comment should be hidden.
    hideme: u64,

    // This comment won't show up.
    bad: u64,
}
```

Shall have this auto-generated for it;
```rust
/// Auto-generated by `derive_getters::Getters`.
impl<'a, T> Funky<'a, T> {
    /// Get field `number` from instance of `Funky`.
    pub fn number(&self) -> &i64 {
        &self.number
    }
    /// This is commented.
    pub fn commented(&self) -> &T {
        &self.commented
    }
    /// This comment is over
    /// many lines.
    /// Here's another line.
    pub fn floating(&self) -> &f32 {
        &self.many_line
    }
    /**
     * This is one of those
     * pesky multi-line
     * comments.
     */
    pub fn multi_line(&'a self) -> &'a str {
        self.multi_line
    }
    /// A doc comment
    pub fn one_comment(&self) -> &u64 {
        &self.one_comment
    }
    /**Comments sourced from a file included at compile time.
*/
    pub fn incl_comment(&self) -> &u64 {
        &self.incl_comment
    }
    #[doc(hidden)]
    /// This comment should be hidden.
    pub fn hideme(&self) -> &u64 {
        &self.hideme
    }
    /// Get field `bad` from instance of `Funky`.
    pub fn bad(&self) -> &u64 {
        &self.bad
    }
}
/// Auto-generated by `derive_getters::Dissolve`.
impl<'a, T> Funky<'a, T> {
    /// Dissolve `Funky` into a tuple consisting of its fields in order of declaration.
    pub fn melt(self) -> (i64, T, f32, &'a str, u16, u64, u64, u64, u64) {
        (
            self.number,
            self.commented,
            self.many_line,
            self.multi_line,
            self.ignore_me,
            self.one_comment,
            self.incl_comment,
            self.hideme,
            self.bad,
        )
    }
}
```

See? Now with comments!

## Testing
With the presence of the new `#[cfg]` feature `auto_copy_getters`, not all tests will run with the usual `cargo test`. To run all tests in one go, give the [cargo-hack](https://crates.io/crates/cargo-hack) crate a try. After installing it, run;
```
cargo hack test --feature-powerset
```

## Caveats
1. `Getters` cannot be derived for unit structs, tuple structs, or enums.
2. `Dissolve` cannot be derived for unit structs or enums.
3. Without `auto_copy_getters`, all getter methods return an immutable reference, `&`, to their field. This means for some types it can get awkward. But with `auto_copy_getters` feature set there won't be any references used in the generated getters for primitive `Copy` types.

## Alternatives
[getset](https://github.com/Hoverbear/getset).