inline_newtype/lib.rs
1///
2/// A rust newtype macro inspired by kotlin's inline class.
3///
4///
5/// When we use
6/// ```rust newtype!(NewTypeOne, u32);```
7/// It generate the struct
8///```
9/// #[derive(Debug, Clone)]
10/// struct UserHomeDirectory {
11/// pub v: u32,
12/// }
13///```
14/// for you.
15/// The ***v*** is the default public field.
16///
17/// ```rust
18/// use inline_newtype::newtype;
19/// use std::path::PathBuf;
20/// newtype!(UserHomeDirectory, PathBuf);
21/// newtype!(UserRuntimeDirectory, PathBuf);
22/// let user_home_directory = UserHomeDirectory { v: PathBuf::from("hello") };
23/// let user_runtime_directory= UserRuntimeDirectory {v: PathBuf::from("hello")};
24/// fn test_newtype_type_func(user_home_directory: UserHomeDirectory) -> UserHomeDirectory{
25/// user_home_directory
26/// }
27/// ```
28/// ```compile_fail
29/// test_newtype_type_func(user_runtime_directory); // mismatch type
30/// ```
31/// You can aslo make the newtype public just adding the pub.
32/// ```rust
33/// use inline_newtype::newtype;
34/// use std::path::PathBuf;
35/// newtype!(UserHomeDirectory, PathBuf, pub);
36/// ```
37///
38/// You also can change the field name if you want.
39/// ```rust
40/// use inline_newtype::newtype;
41/// use std::path::PathBuf;
42/// newtype!(UserHomeDirectory, PathBuf, path_buf);
43/// let user_home_directory = UserHomeDirectory { path_buf: PathBuf::from("hello")};
44/// assert_eq!(user_home_directory.path_buf, PathBuf::from("hello"));
45/// ```
46/// Transform from one newtype to another
47/// ```rust
48/// use inline_newtype::newtype;
49/// use std::path::PathBuf;
50/// newtype!(UserHomeDirectory, PathBuf);
51/// newtype!(UserRuntimeDirectory, PathBuf);
52/// let user_home_directory = UserHomeDirectory { v: PathBuf::from("hello") };
53/// let user_runtime_directory = UserRuntimeDirectory { v: PathBuf::from("hello") };
54/// fn transform_user_home_to_runtime_directory(
55/// mut user_home_directory: UserHomeDirectory,
56/// ) -> UserRuntimeDirectory {
57/// let mut runtime_dir = user_home_directory.v;
58/// runtime_dir.push("runtime_dir");
59/// UserRuntimeDirectory { v: runtime_dir }
60/// }
61///
62
63/// ```
64/// You can also using curly brackets to declare the newtype.
65/// ```rust
66/// use inline_newtype::newtype;
67/// use std::path::PathBuf;
68/// newtype! {UserHomeDirectory, PathBuf, path_buf}
69/// let user_home_directory = UserHomeDirectory { path_buf: PathBuf::from("hello") };
70/// assert_eq!(user_home_directory.path_buf, PathBuf::from("hello"))
71/// ```
72///
73#[macro_export]
74macro_rules! newtype {
75 ($type_name: ident, $type: ty) => {
76 #[derive(Debug, Clone)]
77 struct $type_name {
78 pub v: $type,
79 }
80 };
81 ($type_name: ident, $type: ty, $is_pub:vis) => {
82 #[derive(Debug, Clone)]
83 pub struct $type_name {
84 pub v: $type,
85 }
86 };
87 ($type_name: ident, $type: ty, $access_name: ident) => {
88 #[derive(Debug, Clone)]
89 struct $type_name {
90 pub $access_name: $type,
91 }
92 };
93 ($type_name: ident, $type: ty, $access_name: ident, $is_pub:vis) => {
94 #[derive(Debug, Clone)]
95 $is_pub struct $type_name {
96 pub $access_name: $type,
97 }
98 };
99 {$type_name: ident, $type: ty} => {
100 #[derive(Debug, Clone)]
101 struct $type_name {
102 pub v: $type,
103 }
104 };
105 {$type_name: ident, $type: ty, $is_pub:vis} => {
106 #[derive(Debug, Clone)]
107 pub struct $type_name {
108 pub v: $type,
109 }
110 };
111 {$type_name: ident, $type: ty, $access_name: ident} => {
112 #[derive(Debug, Clone)]
113 struct $type_name {
114 pub $access_name: $type,
115 }
116 };
117 {$type_name: ident, $type: ty, $access_name: ident, $is_pub:vis} => {
118 #[derive(Debug, Clone)]
119 $is_pub struct $type_name {
120 pub $access_name: $type,
121 }
122 };
123}
124
125#[cfg(test)]
126mod tests {
127 use std::path::PathBuf;
128
129 #[test]
130 fn test_new_type() {
131 newtype!(UserHomeDirectory, PathBuf);
132 let user_home_directory = UserHomeDirectory {
133 v: PathBuf::from("hello"),
134 };
135 assert_eq!(user_home_directory.v, PathBuf::from("hello"));
136 }
137
138 #[test]
139 fn test_type_not_equal() {
140 newtype!(UserHomeDirectory, PathBuf);
141 newtype!(UserRuntimeDirectory, PathBuf);
142 let user_home_directory = UserHomeDirectory {
143 v: PathBuf::from("hello"),
144 };
145 let user_runtime_directory = UserRuntimeDirectory {
146 v: PathBuf::from("hello"),
147 };
148 fn test_newtype_type_func(user_home_directory: UserHomeDirectory) -> UserHomeDirectory {
149 user_home_directory
150 }
151 }
152
153 #[test]
154 fn test_transform_newtype() {
155 newtype!(UserHomeDirectory, PathBuf);
156 newtype!(UserRuntimeDirectory, PathBuf);
157 let user_home_directory = UserHomeDirectory {
158 v: PathBuf::from("hello"),
159 };
160 let user_runtime_directory = UserRuntimeDirectory {
161 v: PathBuf::from("hello"),
162 };
163
164 fn transform_user_home_to_runtime_directory(
165 mut user_home_directory: UserHomeDirectory,
166 ) -> UserRuntimeDirectory {
167 let mut runtime_dir = user_home_directory.v;
168 runtime_dir.push("runtime_dir");
169 UserRuntimeDirectory { v: runtime_dir }
170 }
171 }
172
173 #[test]
174 fn test_field_name() {
175 newtype!(UserHomeDirectory, PathBuf, path_buf);
176 let user_home_directory = UserHomeDirectory {
177 path_buf: PathBuf::from("hello"),
178 };
179 assert_eq!(user_home_directory.path_buf, PathBuf::from("hello"))
180 }
181
182 #[test]
183 fn test_curly_brackets_name() {
184 newtype! {UserHomeDirectory, PathBuf, path_buf}
185 let user_home_directory = UserHomeDirectory {
186 path_buf: PathBuf::from("hello"),
187 };
188 assert_eq!(user_home_directory.path_buf, PathBuf::from("hello"))
189 }
190}