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
/*!
A simple builder for constructing or mutating values.

This crate provides a simple `FluentBuilder` structure.
It offers some standard behaviour for constructing values from a given source, or by mutating a default that's supplied later.
This crate is intended to be used within other builders rather than consumed by your users directly.
It's especially useful for managing the complexity of keeping builders ergonomic when they're nested within other builders.

This crate is currently designed around builders that take self by-value instead of by-reference.

# Usage

Create a `FluentBuilder` and construct a default value:

```
use fluent_builder::FluentBuilder;

let value = FluentBuilder::<String>::default()
    .into_value(|| "A default value".to_owned());

assert_eq!("A default value", value);
```

Values can be supplied to the builder directly.
In this case that value will be used instead of constructing the default:

```
# use fluent_builder::FluentBuilder;
let value = FluentBuilder::<String>::default()
    .value("A value".to_owned())
    .into_value(|| "A default value".to_owned());

assert_eq!("A value", value);
```

Mutating methods will either be applied to a concrete value, or the constructed default:

```
# use fluent_builder::FluentBuilder;
let value = FluentBuilder::<String>::default()
    .fluent_mut(|s| s.push_str(" fluent2"))
    .into_value(|| "A default value".to_owned());

assert_eq!("A default value fluent2", value);
```

## Stacking fluent methods

Fluent methods are overriden by default each time `.fluent` is called, but can be configured to maintain state across calls using a generic parameter:

```
use fluent_builder::{FluentBuilder, Stack};

let value = FluentBuilder::<String, Stack>::default()
    .fluent_mut(|s| s.push_str(" fluent1"))
    .fluent_mut(|s| s.push_str(" fluent2"))
    .into_value(|| "A default value".to_owned());

assert_eq!("A default value fluent1 fluent2", value);
```

Which option is best depends on the use-case.
For collection-like values it might make more sense to use stacking builders.
For other kinds of values it probably makes more sense to use overriding builders, so they're the default choice.
Using a generic parameter instead of some value to control whether or not fluent methods are stacked means you can enforce a particular style through Rust's type system.

## Stateful builders

Fluent builders can also be used to thread required state through construction:

```
use fluent_builder::StatefulFluentBuilder;

#[derive(Debug, PartialEq, Eq)]
struct Builder {
    required: String,
    optional: Option<String>,
}

let value = StatefulFluentBuilder::<String, Builder>::from_seed("A required value".to_owned())
    .fluent_mut("A required value".to_owned(), |b| {
        if let Some(ref mut optional) = b.optional.as_mut() {
            optional.push_str(" fluent1");
        }
    })
    .into_value(|s| Builder {
        required: s,
        optional: Some("A default value".to_owned())
    });

assert_eq!("A required value", value.required);
assert_eq!("A default value fluent1", value.optional.unwrap());
```

Stateful builders can also stack fluent methods instead of overriding them.
The API requires each invocation of `fluent` deals with the required state:

```
# #[derive(Debug, PartialEq, Eq)]
# struct Builder {
#     required: String,
#     optional: Option<String>,
# }
use fluent_builder::{StatefulFluentBuilder, Stack};

let value = StatefulFluentBuilder::<String, Builder, Stack>::from_seed("A required value".to_owned())
    .fluent_mut("A required value".to_owned(), |s, b| {
        b.required = s;
        if let Some(ref mut optional) = b.optional.as_mut() {
            optional.push_str(" fluent1");
        }
    })
    .fluent_mut("A required value".to_owned(), |s, b| {
        b.required = s;
        if let Some(ref mut optional) = b.optional.as_mut() {
            optional.push_str(" fluent2");
        }
    })
    .into_value(|s| Builder {
        required: s,
        optional: Some("A default value".to_owned())
    });

assert_eq!("A required value", value.required);
assert_eq!("A default value fluent1 fluent2", value.optional.unwrap());
```

## Within other builders

The `FluentBuilder` and `StatefulFluentBuilder` types are designed to be used within other builders rather than directly.
They just provide some consistent underlying behaviour with respect to assigning and mutating inner builders:

```rust
use fluent_builder::{BoxedFluentBuilder, Stack};

#[derive(Default)]
struct RequestBuilder {
    // Use a `FluentBuilder` to manage the inner `BodyBuilder`
    body: BoxedFluentBuilder<BodyBuilder, Stack>,
}

#[derive(Default)]
struct BodyBuilder {
    bytes: Vec<u8>,
}

impl<B> From<B> for BodyBuilder
where
    B: AsRef<[u8]>
{
    fn from(bytes: B) -> Self {
        BodyBuilder {
            bytes: bytes.as_ref().to_vec()
        }
    }
}

struct Request {
    body: Body
}

struct Body(Vec<u8>);

impl RequestBuilder {
    fn new() -> Self {
        RequestBuilder {
            body: BoxedFluentBuilder::default(),
        }
    }

    // Accept any type that can be converted into a `BodyBuilder`
    // This will override any previously stored state or default
    fn body<B>(mut self, body: B) -> Self
    where
        B: Into<BodyBuilder>
    {
        self.body = self.body.value(body.into());
        self
    }

    // Mutate some `BodyBuilder` without having to name its type
    // If there's no previously supplied concrete value then some
    // default will be given on `build`
    fn body_fluent<F>(mut self, body: F) -> Self
    where
        F: Fn(BodyBuilder) -> BodyBuilder + 'static
    {
        self.body = self.body.fluent(body).boxed();
        self
    }

    fn build(self) -> Request {
        // Get a `Body` by converting the `FluentBuilder` into a `BodyBuilder`
        let body = self.body.into_value(|| BodyBuilder::default()).build();

        Request {
            body: body
        }
    }
}

impl BodyBuilder {
    fn append(mut self, bytes: &[u8]) -> Self {
        self.bytes.extend(bytes);
        self
    }

    fn build(self) -> Body {
        Body(self.bytes)
    }
}

// Use a builder to construct a request using fluent methods
let request1 = RequestBuilder::new()
    .body_fluent(|b| b.append(b"some"))
    .body_fluent(|b| b.append(b" bytes"))
    .build();

// Use a builder to construct a request using a given value
let request2 = RequestBuilder::new()
    .body(b"some bytes")
    .build();

assert_eq!(request1.body.0, request2.body.0);
```

This seems like a lot of boilerplate, but comes in handy when you have a lot of potentially nested builders and need to keep them consistent.
There's nothing really special about the above builders besides the use of `FluentBuilder`.
*/

mod imp;

pub use self::imp::{
    Boxed, BoxedFluentBuilder, BoxedStatefulFluentBuilder, DefaultStack, DefaultStorage,
    FluentBuilder, Inline, Override, Shared, SharedFluentBuilder, SharedStatefulFluentBuilder,
    Stack, StatefulFluentBuilder, TryIntoValue,
};