Macro to 'attach' values statically to a type using static getter and setter methods.
```toml
[dependencies]
type_cell = "0.3"
```
```rust
use type_cell::*;
tycell!{
{String}
[nice_str]
[lazy_str.clone() -> String {"hello"}]
{bool > Vec}
[is_nice]
{!Vec}
[are_nice]
}
fn main(){
String::set_nice_str("world");
assert_eq!(
"hello world",
&format!("{} {}",&String::lazy_str(),String::nice_str())
);
}
```
## 🧱 Basic Usage
- Use the macro: `tycell!{...}`
- Which type should the value be 'attached' on? `u32 {...}`
- Which type does the value have? `static u32:`
- Which settings will it use?
🌟 `once_read` Set it once. Get it read-only! (combine with Mutex/RwLock/... for mutability)
🏁 `once_write` Set it once. Get it mutable, but risk race conditions! (be sure you win the race!)
🦥 `lazy_read` Like `once_read` but set lazy inside the macro!
👹 `lazy_write`Like `once_write` but set lazy inside the macro!!
- examples: `static u32: once_read;` or `static String: lazy_read;`
- What's the name of the default setter method? `set_type()`
- What's the name of the default getter method? `get_type()`
```rust
// Basic Usage
tycell!{ bool {
static Vec: once_read;
set set_vec();
get vec();
}}
// Set it somewhere once:
bool::set_vec(Vec::from([true,false,true]));
// Get it anywhere afterwards:
assert_eq!(&[true,false,true],bool::vec().as_slice());
```
The default setter parameter is a dynamic `Into<..>` and will use `.into()`.
This means in this example you could also set it like this:
```rust
bool::set_vec([true,false,true]);
assert_eq!(&[true,false,true],bool::vec().as_slice());
```
## ⚗ Advanced Usage
Multiple Setter and Getter with different parameters and return types can be defined!
There are two ways of doing it:
- **Methods:**
- Use inline methods for simple conversions!
- `set set_bool(Option): do.is_some();`
- `get get_bool() -> bool: static.clone();`
- **Function:**
- Use a function with correct parameters/return types and is accessible in the same file!
- Use `=` before the function meta!
- `set =set_base_fn(a:Option);`
- `get =get_base_fn() -> bool;`
```rust
// Advanced Usage
fn set_by_function (a:Option) -> bool {a.is_some()}
fn get_by_function (a:&bool) -> bool {a.clone()}
tycell!{ bool {
static bool: once_read;
set set_raw();
set set_by_methods(Option): do.is_some();
set =set_by_function(a:Option);
get get_raw();
get get_by_methods() -> bool: static.clone();
get =get_by_function() -> bool;
}}
bool::set_by_methods(None);
assert_eq!(false,bool::get_by_methods());
```
Methods with parameters are supported in two different ways:
- **Constants:**
- Using `=` before a constant value!
- `set set_number(u32): do.clamp(=0,=100);`
- `get get_number() -> bool: static.clamp(=0,=100);`
- **Pass Through:**
- Naming the values with its types will pass it into the function!
- `set set_number(u32): do.clamp(min:u32,max:u32);`
- `get get_number() -> bool: static.clamp(min:u32,max:u32);`
```rust
// Advanced Usage
tycell!{ u32 {
static u32: once_read;
set set_raw();
set set_by_methods(u32): do.clamp(=0,=100);
set set_pass(u32): do.clamp(min:u32,max:u32);
get get_raw();
get get_by_methods() -> u32: static.add(=5);
get get_pass() -> u32: static.add(val:u32);
}}
// Sets value to 1000.clamp(0,123) = 123
u32::set_pass(1000,0,123);
// Gets 123.add(5) = 128
assert_eq!(128,u32::get_by_methods());
```
## 🧊 Constant
You can also set const values!
```rust
// Constant
tycell!{ u32 {
const u32 = 100;
get number();
}}
// Gets 10!
assert_eq!(10,u32::number());
```
## 👹 Risky Mutable Options
⚠`Only use this if you're sure there are no race conditions (or they don't matter) or for debug purposes!`
To make the static value mutable, use `once_write` or `lazy_write`.
```rust
// Risky Mutable
tycell!{ u32 {
static u32: risky_write;
set set_number();
get number();
}}
// Set it somewhere once:
u32::set_number(5u32);
// Default getter is mutable already
*u32::number() = 10;
// Gets 10!
assert_eq!(10,*u32::number());
```
## 🦥 As Lazy Static
To create a lazy static value, use the `lazy_read` option and use a block instead of the setter function!
```rust
// Lazy Static
tycell!{ u32 {
static HashMap: lazy_read;
set {
let mut map = HashMap::new();
for i in 0..100 {
map.insert(i,i.to_string());
}
map
}
get get_lazy_map();
get get_lazy() -> Option<&String>: static.get(id:&u32);
}}
// Gets Some("3":&String)
assert_eq!(&"3",&u32::get_lazy(&3).unwrap());
```
## ➡ Simple Mapping
If you only need the default getter and setters, there is a short form:
```rust
// Simple Usage
tycell!{
// store a vec of bools on the bool type
// a single specifier inside [..] will use once_read
// adding 'mut' before it sets it to once_write
// adding a block {} after the specifier will use lazy_.. instead of once_..
bool > Vec: [bools] [mut more_bools] [lazy_bools{vec![true,false]}];
// adding '= value' after the specifier will set a constant value
bool > u32: [number=100];
}
bool::set_bools([true,false]);
bool::set_more_bools([true,false]);
```
If you only attach values of the same type as their parent:
```rust
// Simplest Usage
tycell!{
// Same as bool > bool: [is_nice];
bool: [is_nice];
}
```
If you want to attach a type to its single generic type, e.g. `u32 > Vec` you can use `!Vec`.
Increase the number of `!` to set the level, e.g. `u32 > Vec>` <=> `!!Vec>`.
```rust
tycell!{
!Vec:[is_nice];
}
```
You can't mix different types of left-handed syntax, unless wrapped in `{}`
```rust
// working
tycell!{
{!Vec} [is_nice]
{bool>Vec} [is_v_nice]
{bool} [is_x_nice]
}
// NOT working
tycell!{
!Vec: [is_nice];
bool>Vec: [is_v_nice];
bool: [is_x_nice];
}
```
You can also chain methods for the getter and adjust its return type.
```rust
tycell!{
{String}
[clone_str.clone()->String]
[clone_lazy_str.clone()->String{"test"}]
}
```
## ➡ Simple (Hash)Maps and Vecs
Ease up getting values from a HasmMap-esque types, by using after the name.
if no key is provided, the type is set to a Vec<..> instead.
```rust
// uses anythng named TyMap for flaxibility
use std::collections::HashMap as TyMap;
tycell!{
// same as above, but after the specifier
bool > bool: [bools] [mut more_bools] [lazy_bools{[(1,true)]}];
}
bool::set_bools([(1,true)]);
bool::set_more_bools([(1,true)]);
```
## 🔗 Related Projects
- bevy_cell - Attach bevy Handle and Entity to types.
---
### License
Licensed under either of Apache License, Version
2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.