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
//! Stack based string with customized max-size
//!
//! A stack based strings with a maximum (customizable) size.
//!
//! **Never panics (all panic branches are impossible and therefore removed at compile time)**
//!
//! ## Why
//!
//! Data is generally bounded, you don't want a phone number with 30 characters, nor a username with 100. You probably don't even support it in your database.
//!
//! Why pay the cost of heap allocations of strings with unlimited capacity if you have limited boundaries?
//!
//! Array based strings always occupy the full space in memory, so they may use more size than dynamic strings.
//!
//! Array based strings are generally faster to create, clone and append than heap based strings (custom allocators and thread-locals may help with heap based ones).
//!
//! There are other stack based strings out there, they generally can grow (heap allocate), but the stack based size is defined by the library implementor, we go through a different route (fully stack based with customizable maximum size - per type)
//!
//! ArrayStrings types are created through a macro with customizable maximum size (implementing the appropriate traits)
//!
//! ```rust
//! // Always occupies 21 bytes of memory (in the stack)
//! //
//! // String's current (2018) implementation always uses 24 bytes + up to 20 bytes (actual username)
//! // - Assuming 64 bit usize
//! //
//! // Remember that UTF-8 characters can use up to 4 bytes
//! # #[macro_use]
//! # extern crate arraystring;
//! # fn main() {
//! impl_string!(struct Username(20));
//! # }
//! ```
//!
//! ## Features
//!
//! **default:** `std`
//!
//! - `std` enabled by default, enables `std` compatibility (remove it to be `#[no_std]` compatible)
//! - `serde-traits` enables serde traits integration (`Serialize`/`Deserialize`)
//! - `diesel-traits` enables diesel traits integration (opperates like `String`)
//! - `logs` enables internal logging (you probably don't need it)
//!
//! ## Examples
//!
//! ```rust
//! #[macro_use]
//! extern crate arraystring;
//! use arraystring::{error::Error, prelude::*};
//!
//! impl_string!(pub struct Username(20));
//! impl_string!(pub struct Role(5));
//!
//! #[derive(Debug)]
//! pub struct User {
//! pub username: Username,
//! pub role: Role,
//! }
//!
//! fn main() -> Result<(), Error> {
//! let user = User {
//! username: Username::try_from_str("user")?,
//! role: Role::try_from_str("admin")?
//! };
//! println!("{:?}", user);
//!
//! Ok(())
//! }
//! ```
//!
//! ## Licenses
//!
//! MIT and Apache-2.0
extern crate log;
extern crate env_logger;
pub extern crate diesel;
pub extern crate serde;
/// Remove logging macros when they are disabled (at compile time)
pub extern crate std as core;
/// Most used traits and data-strucutres
/// [`ArrayString`]'s buffer index
///
/// [`ArrayString`]: ./array/trait.ArrayString.html
pub type Size = u8;
pub use ArrayString;
impl_string!;
impl_string!;
impl_string!;