-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add try_setter option and generate appropriate methods #72
Changes from 11 commits
fe38226
f0772df
4cec554
85f4d5a
0b59e93
a56e870
6d497bc
24d7eb4
79491a5
fd7deeb
79e4474
0600c05
1510419
22f49f0
ec3cc06
12daa64
c629cbd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,16 @@ | |
All notable changes to this project will be documented in this file. | ||
This project adheres to [Semantic Versioning](http://semver.org/). | ||
|
||
## [0.4.3] - 2017-04-13 | ||
|
||
### Added | ||
- try_setters, e.g. `#[builder(try_setter)]`. These setters are exposed alongside the | ||
normal field setters and allow callers to pass in values which have | ||
fallible conversions to the needed type through `TryInto`. This attribute | ||
can only be used on nightly when until `#![feature(try_from)]` is declared | ||
in the consuming crate's root; this will change when Rust issue | ||
[#33417](https://github.com/rust-lang/rust/issues/33417) is resolved. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice summary! 👍 |
||
|
||
## [0.4.2] - 2017-04-10 | ||
|
||
### Fixed | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//! This example illustrates the use of try-setters. | ||
//! Tests are suppressed so that this doesn't break the build on stable. | ||
#![cfg(not(test))] | ||
#![feature(try_from)] | ||
|
||
#[macro_use] | ||
extern crate derive_builder; | ||
|
||
use std::convert::TryFrom; | ||
use std::net::{IpAddr, AddrParseError}; | ||
use std::str::FromStr; | ||
use std::string::ToString; | ||
|
||
/// Temporary newtype hack around lack of TryFrom implementations | ||
/// in std. The rust-lang issue on the subject says that there will be a | ||
/// blanket impl for everything that currently implements FromStr, which | ||
/// will make this feature much more useful for input validation. | ||
#[derive(Debug, Clone, PartialEq)] | ||
pub struct MyAddr(IpAddr); | ||
|
||
impl From<IpAddr> for MyAddr { | ||
fn from(v: IpAddr) -> Self { | ||
MyAddr(v) | ||
} | ||
} | ||
|
||
impl<'a> TryFrom<&'a str> for MyAddr { | ||
type Err = AddrParseError; | ||
|
||
fn try_from(v: &str) -> Result<Self, AddrParseError> { | ||
Ok(MyAddr(IpAddr::from_str(v)?)) | ||
} | ||
} | ||
|
||
#[derive(Builder, Debug, PartialEq)] | ||
#[builder(try_setter, setter(into))] | ||
struct Lorem { | ||
pub name: String, | ||
pub addr: MyAddr, | ||
} | ||
|
||
fn main() { | ||
create("Jane", "1.2.3.4").unwrap(); | ||
create("Bobby", "").unwrap_err(); | ||
} | ||
|
||
fn create(name: &str, addr: &str) -> Result<Lorem, String> { | ||
// Fallible and infallible setters can be mixed freely when using | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @colin-kiegel can you please try running There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me guess, does the comment appear at random places in the generated output? :-) I noticed very strange distributions of comments before. I could imagine that this is caused by the syn crate, which we use to parse the input into an ast. But didn't investigate it, because it didn't cause any trouble. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems to consistently get moved into the |
||
// the mutable builder pattern. | ||
LoremBuilder::default() | ||
.name(name) | ||
.try_addr(addr).map_err(|e| e.to_string())? | ||
.build() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -216,6 +216,52 @@ | |
//! } | ||
//! ``` | ||
//! | ||
//! ## Fallible Setters | ||
//! | ||
//! Alongside the normal setter methods, you can expose fallible setters which are generic over | ||
//! the `TryInto` trait. TryInto is a not-yet-stable trait | ||
//! (see rust-lang issue [#33417](https://github.com/rust-lang/rust/issues/33417)) similar to | ||
//! `Into` with the key distinction that the conversion can fail, and therefore produces a `Result`. | ||
//! | ||
//! You can only declare the `try_setter` attribute today if you're targeting nightly, and you have | ||
//! to add `#![feature(try_from)]` to your crate to use it. | ||
//! | ||
//! | ||
//! ```rust,ignore | ||
//! #![feature(try_from)] | ||
//! # #[macro_use] | ||
//! # extern crate derive_builder; | ||
//! # | ||
//! #[derive(Builder, Debug, PartialEq)] | ||
//! #[builder(try_setter, setter(into))] | ||
//! struct Lorem { | ||
//! pub name: String, | ||
//! pub ipsum: u8, | ||
//! } | ||
//! | ||
//! #[derive(Builder, Debug, PartialEq)] | ||
//! struct Ipsum { | ||
//! #[builder(try_setter, setter(into, name = "foo"))] | ||
//! pub dolor: u8, | ||
//! } | ||
//! | ||
//! fn main() { | ||
//! LoremBuilder::default() | ||
//! .try_ipsum(1u16).unwrap() | ||
//! .name("hello") | ||
//! .build() | ||
//! .expect("1 fits into a u8"); | ||
//! | ||
//! IpsumBuilder::default() | ||
//! .try_foo(1u16) | ||
//! .unwrap() | ||
//! .build() | ||
//! .expect("1 fits into a u8"); | ||
//! } | ||
//! ``` | ||
//! | ||
//! A complete example of using fallible setters is available in `examples/try_setter.rs`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please add a note that the name and visibility are inherited from the You could change the example into something like this, to better explain it? //! # #[macro_use]
//! # extern crate derive_builder;
//! #
//! #[derive(Builder, Debug, PartialEq)]
//! struct Lorem {
//! #[builder(try_setter, setter(name="foo"))]
//! pub ipsum: u8,
//! } |
||
//! | ||
//! ## Default Values | ||
//! | ||
//! You can define default values for each field via annotation by `#[builder(default="...")]`, | ||
|
@@ -366,6 +412,9 @@ | |
//! - If derive_builder depends on your crate, and vice versa, then a cyclic | ||
//! dependency would occur. To break it you could try to depend on the | ||
//! [`derive_builder_core`] crate instead. | ||
//! - The `try_setter` attribute and `owned` builder pattern are not compatible in practice; | ||
//! an error during building will consume the builder, making it impossible to continue | ||
//! construction. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice catch :-) |
||
//! | ||
//! ## Debugging Info | ||
//! | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#![cfg_attr(feature = "nightlytests", feature(try_from))] | ||
|
||
use std::net::IpAddr; | ||
|
||
#[macro_use] | ||
extern crate derive_builder; | ||
|
||
#[derive(Debug, Clone, Builder)] | ||
#[builder(try_setter)] | ||
pub struct Lorem { | ||
source: IpAddr, | ||
dest: IpAddr, | ||
name: String, | ||
} | ||
|
||
#[derive(Default, Debug, Clone, Builder)] | ||
#[builder(default, setter(prefix = "set", into), try_setter)] | ||
pub struct Ipsum { | ||
source: Option<IpAddr>, | ||
name: String, | ||
} | ||
|
||
fn main() { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when until
->when