component_model 0.7.0

Revolutionary type-safe component assignment for Rust. Build complex objects with zero boilerplate using derive macros and type-driven field setting. Perfect for configuration builders, fluent APIs, and object composition patterns.
Documentation
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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
<!-- {{# generate.module_header{} #}} -->

# Module :: component_model

[![experimental](https://raster.shields.io/static/v1?label=&message=experimental&color=orange)](https://github.com/emersion/stability-badges#experimental)
[![rust-status](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_push.yml/badge.svg)](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_push.yml)
[![docs.rs](https://img.shields.io/docsrs/component_model?color=e3e8f0&logo=docs.rs)](https://docs.rs/component_model)
[![Open in Gitpod](https://raster.shields.io/static/v1?label=try&message=online&color=eee&logo=gitpod&logoColor=eee)](https://gitpod.io/#RUN_PATH=.,SAMPLE_FILE=module%2Fcore%2Fcomponent_model%2Fexamples%2Fcomponent_model_trivial.rs,RUN_POSTFIX=--example%20module%2Fcore%2Fcomponent_model%2Fexamples%2Fcomponent_model_trivial.rs/https://github.com/Wandalen/wTools)
[![discord](https://img.shields.io/discord/872391416519737405?color=eee&logo=discord&logoColor=eee&label=ask)](https://discord.gg/m3YfbXpUUY)

Revolutionary type-safe component assignment for Rust. Build complex objects with zero boilerplate using derive macros and type-driven field setting. Perfect for configuration builders, fluent APIs, and object composition patterns.

## ๐Ÿš€ Why Component Model?

Traditional struct initialization is verbose and error-prone:

```rust
# struct Config { host : String, port : i32 }
# struct ConfigBuilder;
# impl ConfigBuilder {
#   fn new() -> Self { ConfigBuilder }
#   fn host( self, _ : &str ) -> Self { self }
#   fn port( self, _ : i32 ) -> Self { self }
#   fn build( self ) -> Config { Config { host : "".to_string(), port : 0 } }
# }
// Traditional approach - repetitive and fragile
let config = Config
{
  host : "localhost".to_string(),
  port : 8080,
};

// Builder pattern - lots of boilerplate
let config = ConfigBuilder::new()
.host( "localhost" )
.port( 8080 )
.build();
```

**Component Model approach** - Clean, type-safe, zero boilerplate:

```rust
use component_model::Assign;

#[ derive( Default, Assign ) ]
struct Config
{
  host : String,
  port : i32,
}

// Set components by type - no field names needed!
let mut config = Config::default();
config.assign( "localhost" );  // Automatically sets String field
config.assign( 8080 );         // Automatically sets i32 field  

// Or use fluent style
let config = Config::default()
.impute( "localhost" )
.impute( 8080 );
```

## โœจ Key Features

- **๐ŸŽฏ Type-driven assignment** - Set fields by component type, not field name
- **๐Ÿ”ง Zero boilerplate** - Derive macros generate all implementations automatically  
- **๐ŸŒŠ Fluent APIs** - Chainable `impute()` method for builder patterns
- **๐Ÿ›ก๏ธ Type safety** - All assignments checked at compile time
- **๐Ÿ”„ Flexible conversion** - Accepts any type convertible to target field type
- **๐Ÿ“ฆ Multiple assignment** - Set multiple components with `ComponentsAssign`
- **โšก Popular types support** - Built-in support for Duration, PathBuf, SocketAddr, and more
- **๐Ÿ—๏ธ ComponentModel derive** - Unified derive macro combining all functionality

## ๐Ÿš€ Quick Start

Add to your `Cargo.toml`:

```toml
[ dependencies ]
component_model = "0.4"
```

### Feature Flags

Component Model follows granular feature gating for minimal builds:

```toml
[ dependencies ]
# Minimal version - no features enabled by default  
component_model = { version = "0.4", default-features = false }

# Enable specific features as needed
component_model = { version = "0.4", features = [ "derive_component_model" ] }

# Or enable all features (default)
component_model = { version = "0.4", features = [ "full" ] }
```

Available features:
- **`enabled`** - Master switch for core functionality
- **`full`** - All features (enabled by default)
- **`derive_component_model`** - Unified ComponentModel derive macro
- **`derive_component_assign`** - Basic Assign derive macro
- **`derive_components_assign`** - Multiple component assignment
- **`derive_component_from`** - Component creation from single values
- **`derive_from_components`** - Component creation from multiple values

## ๐Ÿ“– Core Concepts

### 1. Basic Assignment with ComponentModel

```rust
use component_model::{ ComponentModel, Assign };

#[ derive( Default, Debug, ComponentModel ) ]
struct Person
{
  age : i32,
  name : String,
}

fn main()
{
  let mut person = Person::default();
  
  // Type-driven assignment - no field names!
  person.assign( 25 );           // Sets age : i32  
  person.assign( "Alice" );      // Sets name : String
  
  println!( "{:?}", person );    // Person { age: 25, name: "Alice" }
}
```

### 2. Popular Types Support

ComponentModel provides built-in support for popular Rust types with intelligent conversion:

```rust
use component_model::{ ComponentModel, Assign };
use std::time::Duration;
use std::path::PathBuf;

#[ derive( Default, Debug, ComponentModel ) ]
struct Config
{
  timeout : Duration,
  config_path : PathBuf,
  port : i32,
}

fn main()
{
  let mut config = Config::default();
  
  // Duration from seconds (u64)
  config.assign( 30u64 );  // Duration::from_secs( 30 )
  
  // Duration from fractional seconds (f64)  
  config.assign( 2.5f64 ); // Duration::from_secs_f64( 2.5 )
  
  // PathBuf from string slice
  config.assign( "/etc/app.conf" ); // PathBuf::from( "/etc/app.conf" )
  
  // i32 assignment
  config.assign( 8080i32 );
}
```

### 3. Enum Fields in Structs

ComponentModel works with structs that contain enum fields, enabling type-safe enum assignment:

```rust
use component_model::{ ComponentModel, Assign };

#[ derive( Debug, PartialEq ) ]
enum Status
{
  Pending,
  Processing { progress : f64 },
  Completed { result : String },
  Failed { error : String },
}

impl Default for Status
{
  fn default() -> Self { Status::Pending }
}

#[ derive( Default, Debug, ComponentModel ) ]
struct Task
{
  id : u32,
  status : Status,
  priority : u8,
}

fn main()
{
  let mut task = Task::default();
  
  // Use field-specific methods with enums
  task.id_set( 42u32 );
  task.priority_set( 5u8 );
  task.status_set( Status::Processing { progress: 0.75 } );
  
  println!( "{:?}", task );
  
  // Fluent style with enums
  let completed_task = Task::default()
    .id_with( 100u32 )
    .status_with( Status::Completed { result: "Success".to_string() } )
    .priority_with( 1u8 );
    
  match completed_task.status {
    Status::Completed { result } => println!( "Task completed: {}", result ),
    _ => println!( "Unexpected status" ),
  }
}
```

#### Complex Enum Fields

```rust
use component_model::{ ComponentModel, Assign };
use std::time::Duration;

#[ derive( Debug ) ]
enum ConnectionState
{
  Disconnected,
  Connecting { timeout : Duration },
  Connected { session_id : String },
}

impl Default for ConnectionState
{
  fn default() -> Self { ConnectionState::Disconnected }
}

#[ derive( Default, Debug, ComponentModel ) ]
struct NetworkService
{
  name : String,
  state : ConnectionState,
  retry_count : u32,
}

fn main()
{
  let mut service = NetworkService::default();
  
  // Field-specific methods work seamlessly with enum fields
  service.name_set( "WebSocket".to_string() );
  service.retry_count_set( 3u32 );
  service.state_set( ConnectionState::Connected { 
    session_id: "sess_12345".to_string() 
  } );
  
  // Fluent pattern with complex enums
  let connecting_service = NetworkService::default()
    .name_with( "HTTP Client".to_string() )
    .state_with( ConnectionState::Connecting { 
      timeout: Duration::from_secs( 30 )
    } )
    .retry_count_with( 0u32 );
    
  println!( "{:?}", connecting_service );
}
```

> **Note**: Direct ComponentModel derive on enums is planned for future releases. Currently, enums work as field types in structs with ComponentModel.

### 4. Fluent Builder Pattern

```rust
# use component_model::{ ComponentModel, Assign };
# #[ derive( Default, ComponentModel ) ]
# struct Person { name : String, age : i32 }
let person = Person::default()
.impute( "Bob" )           // Chainable assignment
.impute( 30 );             // Returns Self for chaining
```

### 5. Multiple Component Assignment

```rust
use component_model::{ ComponentModel, Assign };

#[ derive( Default, ComponentModel ) ]
struct ServerConfig
{
  host : String,
  port : i32, 
}

let mut config = ServerConfig::default();
config.assign( "localhost" );    // String component
config.assign( 8080 );           // i32 component
```

### 6. Manual Implementation (Advanced)

For custom behavior, implement traits manually:

```rust
use component_model::prelude::*;

struct Database
{
  url : String,
  pool_size : usize,
}

impl< T : Into< String > > Assign< String, T > for Database
{
  fn assign( &mut self, component : T )
  {
    self.url = component.into();
  }
}

impl< T : Into< usize > > Assign< usize, T > for Database
{  
  fn assign( &mut self, component : T )
  {
    self.pool_size = component.into();
  }
}
```

## ๐Ÿ“š Available Derive Macros

- **`ComponentModel`** - โญ **Recommended** - Unified derive combining all functionality
- **`Assign`** - Basic component assignment by type
- **`ComponentsAssign`** - Multiple component assignment from tuples  
- **`ComponentFrom`** - Create objects from single components
- **`FromComponents`** - Create objects from multiple components

## ๐ŸŽฏ Real-World Use Cases

### Configuration Management with Popular Types
```rust
use component_model::{ ComponentModel, Assign };
use std::time::Duration;
use std::path::PathBuf;

#[ derive( Default, ComponentModel ) ]
struct DatabaseConfig
{
  host : String,
  port : i32,
  timeout : Duration,
}

let config = DatabaseConfig::default()
.impute( "postgres.example.com" )    // String
.impute( 5432 )                      // i32  
.impute( 30u64 );                    // Duration from seconds
```

### HTTP Client Builders
```rust
use component_model::{ ComponentModel, Assign };
use std::time::Duration;

#[ derive( Default, ComponentModel ) ]
struct HttpClient
{
  base_url : String,
  timeout : Duration,
}

let client = HttpClient::default()
.impute( "https://api.example.com" )
.impute( 30.0f64 );  // Duration from fractional seconds
```

### Game Entity Systems
```rust
use component_model::{ ComponentModel, Assign };

#[ derive( Default, ComponentModel ) ]
struct Player
{
  name : String,
  level : i32,
}

// Initialize components
let mut player = Player::default();
player.assign( "Hero" );
player.assign( 1 );
```

## ๐Ÿงช Examples

Explore the [examples directory](examples/) for comprehensive usage patterns:

- **[`000_basic_assignment.rs`]examples/000_basic_assignment.rs** - Basic component assignment
- **[`001_fluent_builder.rs`]examples/001_fluent_builder.rs** - Fluent builder pattern
- **[`002_multiple_components.rs`]examples/002_multiple_components.rs** - Multiple component handling
- **[`003_component_from.rs`]examples/003_component_from.rs** - Component creation patterns
- **[`004_working_example.rs`]examples/004_working_example.rs** - Real-world usage scenarios
- **[`component_model_trivial.rs`]examples/component_model_trivial.rs** - Minimal example

## ๐Ÿ“‹ Supported Popular Types

ComponentModel includes built-in intelligent conversion for:

| Type | Input Types | Example |
|------|-------------|---------|
| `Duration` | `u64`, `f64`, `(u64, u32)` | `config.assign( 30u64 )` |
| `PathBuf` | `&str`, `String` | `config.assign( "/path/file" )` |
| `SocketAddr` | *Coming soon* | String parsing planned |
| `HashMap` | *Framework ready* | Vec conversion planned |
| `HashSet` | *Framework ready* | Vec conversion planned |

## โš ๏ธ Important Limitations

**Type Ambiguity**: When a struct has multiple fields of the same type, `assign()` becomes ambiguous and won't compile. This is by design for type safety.

```rust
# use component_model::{ ComponentModel, Assign };
# #[ derive( Default, ComponentModel ) ]
struct Config
{
  host : String,
  database : String,  // Multiple String fields cause ambiguity
}

// This won't compile due to ambiguity:
// let mut config = Config::default();
// config.assign( "localhost" );  // Error: which String field?
```

**Workarounds**:
1. Use different types when possible (e.g., `String` vs `PathBuf`)
2. Use direct field assignment: `config.host = "localhost".to_string();`
3. Implement manual `Assign` traits for specific use cases

## ๐Ÿ”— Learn More

- **[๐Ÿ“ Examples]examples/** - Step-by-step examples showing all features
- **[๐Ÿ“– API Docs]https://docs.rs/component_model** - Complete API reference  
- **[๐Ÿ™ Source Code]https://github.com/Wandalen/wTools/tree/master/module/core/component_model** - Contribute or report issues
- **[๐Ÿ’ฌ Discord]https://discord.gg/m3YfbXpUUY** - Get help and discuss

---

*Made with โค๏ธ as part of the [wTools](https://github.com/Wandalen/wTools) ecosystem*