1#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
2#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
3#![forbid(clippy::format_push_string)]
4
5use core::net::*;
6
7#[cfg(not(feature = "std"))]
8include!("no_std.rs");
9#[cfg(feature = "std")]
10use std::{borrow::Cow, collections::HashSet, fmt::Display, rc::Rc, sync::Arc};
11
12#[cfg(feature = "phf")]
13use std::collections::HashMap;
14
15#[cfg(feature = "derive")]
16pub use const_gen_derive::*;
17
18#[cfg(test)]
19mod test;
20
21#[cfg(feature = "either")]
22mod either;
23
24#[macro_export]
29macro_rules! const_definition
30{
31 ( $(#[$attr:meta])* $vis:vis $ty:ty) =>
32 {
33 <$ty>::const_definition(stringify!($(#[$attr])*), stringify!($vis))
34 }
35}
36
37#[macro_export]
42macro_rules! const_declaration
43{
44 ( $(#[$attr:meta])* $vis:vis $name:ident = $($val:tt)*) =>
45 {
46 $($val)*.const_declaration(stringify!($(#[$attr])*), stringify!($vis), stringify!($name))
47 }
48}
49
50#[macro_export]
55macro_rules! static_declaration
56{
57 ( $(#[$attr:meta])* $vis:vis $name:ident = $($val:tt)*) =>
58 {
59 $($val)*.static_declaration(stringify!($(#[$attr])*), stringify!($vis), stringify!($name))
60 }
61}
62
63#[macro_export]
65macro_rules! const_array_declaration
66{
67 ( $(#[$attr:meta])* $vis:vis $name:ident = $($val:tt)*) =>
68 {
69 $($val)*.const_array_declaration(stringify!($(#[$attr])*), stringify!($vis), stringify!($name))
70 }
71}
72
73#[macro_export]
75macro_rules! static_array_declaration
76{
77 ( $(#[$attr:meta])* $vis:vis $name:ident = $($val:tt)*) =>
78 {
79 $($val)*.static_array_declaration(stringify!($(#[$attr])*), stringify!($vis), stringify!($name))
80 }
81}
82
83#[derive(Debug, Copy, Clone, Eq, PartialEq)]
85pub enum DeclarationType {
86 Const,
87 Static,
88}
89
90impl Display for DeclarationType {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 f.write_str(match self {
93 DeclarationType::Const => "const",
94 DeclarationType::Static => "static",
95 })
96 }
97}
98
99pub trait CompileConst {
101 fn const_type() -> String;
106 fn const_val(&self) -> String;
108 fn declaration(
130 &self,
131 attrs: &str,
132 vis: &str,
133 declaration_type: DeclarationType,
134 name: &str,
135 ) -> String {
136 format!(
137 "#[allow(clippy::redundant_static_lifetimes)] {}{}{}{}{} {}: {} = {};",
138 if attrs.is_empty() { "" } else { attrs },
139 if attrs.is_empty() { "" } else { " " },
140 vis,
141 if vis.is_empty() { "" } else { " " },
142 declaration_type,
143 name,
144 Self::const_type(),
145 self.const_val()
146 )
147 }
148 fn const_declaration(&self, attrs: &str, vis: &str, name: &str) -> String {
152 self.declaration(attrs, vis, DeclarationType::Const, name)
153 }
154 fn static_declaration(&self, attrs: &str, vis: &str, name: &str) -> String {
158 self.declaration(attrs, vis, DeclarationType::Static, name)
159 }
160 fn const_definition(_attrs: &str, _vis: &str) -> String {
168 String::new()
169 }
170}
171
172pub trait CompileConstArray {
174 fn const_array_type(&self) -> String;
176 fn const_array_val(&self) -> String;
178 fn array_declaration(
180 &self,
181 attrs: &str,
182 vis: &str,
183 declaration_type: DeclarationType,
184 name: &str,
185 ) -> String {
186 format!(
187 "{}{}{}{}{} {}: {} = {};",
188 if attrs.is_empty() { "" } else { attrs },
189 if attrs.is_empty() { "" } else { " " },
190 vis,
191 if vis.is_empty() { "" } else { " " },
192 declaration_type,
193 name,
194 self.const_array_type(),
195 self.const_array_val()
196 )
197 }
198
199 fn const_array_declaration(&self, attrs: &str, vis: &str, name: &str) -> String {
201 self.array_declaration(attrs, vis, DeclarationType::Const, name)
202 }
203 fn static_array_declaration(&self, attrs: &str, vis: &str, name: &str) -> String {
205 self.array_declaration(attrs, vis, DeclarationType::Static, name)
206 }
207}
208
209macro_rules! numerics
210{
211 ( $($t:ty),* ) =>
212 {
213 $(impl CompileConst for $t
214 {
215 fn const_type() -> String
216 {
217 stringify!($t).to_string()
218 }
219
220 fn const_val(&self) -> String
221 {
222 format!("{}{}", self, stringify!($t))
223 }
224 })*
225 }
226}
227numerics!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64);
228
229macro_rules! strings
230{
231 ( $($t:ty),* ) =>
232 {
233 $(
234 impl CompileConst for $t
235 {
236 fn const_type() -> String
237 {
238 "&'static str".to_string()
239 }
240
241 fn const_val(&self) -> String
242 {
243 format!("\"{}\"", self)
244 }
245 }
246 impl CompileConstArray for $t
247 {
248 fn const_array_type(&self) -> String
249 {
250 format!("[char; {}]", self.chars().count())
251 }
252
253 fn const_array_val(&self) -> String
254 {
255 format!("[{}]", self.chars().map(|c| format!("'{}',", c)).collect::<Vec<String>>().concat())
256 }
257 }
258 )*
259 }
260}
261strings!(String, &str, str);
262
263macro_rules! slices
264{
265 ( $($t:ty),* ) =>
266 {
267 $(
268 impl<T: CompileConst> CompileConst for $t
269 {
270 fn const_type() -> String
271 {
272 format!("&'static [{}]", T::const_type())
273 }
274
275 fn const_val(&self) -> String
276 {
277 format!("&[{}]", self
278 .into_iter()
279 .map(|e| e.const_val())
280 .collect::<Vec<String>>()
281 .join(","))
282 }
283 }
284 impl<T: CompileConst> CompileConstArray for $t
285 {
286 fn const_array_type(&self) -> String
287 {
288 format!("[{}; {}]", T::const_type(), self.iter().count())
289 }
290
291 fn const_array_val(&self) -> String
292 {
293 format!("[{}]", self
294 .into_iter()
295 .map(|e| e.const_val())
296 .collect::<Vec<String>>()
297 .join(","))
298 }
299 }
300 )*
301 }
302}
303slices!(Vec<T>, &[T]);
304
305macro_rules! derefs
306{
307 ( $($t:ty $(=> $bound:tt)?),* ) =>
308 {
309 $(
310 impl<T: CompileConst $(+ $bound)? > CompileConst for $t
311 {
312 fn const_type() -> String
313 {
314 T::const_type()
315 }
316 fn const_val(&self) -> String
317 {
318 (**self).const_val()
319 }
320 }
321 impl<T: CompileConstArray $(+ $bound)? > CompileConstArray for $t
322 {
323 fn const_array_type(&self) -> String
324 {
325 (**self).const_array_type()
326 }
327
328 fn const_array_val(&self) -> String
329 {
330 (**self).const_array_val()
331 }
332 }
333 )*
334 }
335}
336derefs!(
337 Box<T>,
338 Cow<'_, T> => Clone,
339 Rc<T>,
340 Arc<T>
341);
342
343impl CompileConst for char {
344 fn const_type() -> String {
345 "char".to_owned()
346 }
347
348 fn const_val(&self) -> String {
349 format!("'{}'", *self)
350 }
351}
352
353impl CompileConst for bool {
354 fn const_type() -> String {
355 "bool".to_owned()
356 }
357
358 fn const_val(&self) -> String {
359 if *self { "true" } else { "false" }.to_owned()
360 }
361}
362
363impl<T: CompileConst> CompileConst for Option<T> {
364 fn const_type() -> String {
365 format!("Option<{}>", T::const_type())
366 }
367
368 fn const_val(&self) -> String {
369 match self {
370 Some(t) => format!("Some({})", t.const_val()),
371 None => String::from("None"),
372 }
373 }
374}
375
376#[cfg(feature = "phf")]
377impl<K: CompileConst, V: CompileConst> CompileConst for HashMap<K, V> {
378 fn const_type() -> String {
379 format!("phf::Map<{}, {}>", K::const_type(), V::const_type())
380 }
381
382 fn const_val(&self) -> String {
383 format!(
384 "phf::phf_map!{{{}}}",
385 self.iter()
386 .map(|(k, v)| format!("{} => {}", k.const_val(), v.const_val()))
387 .collect::<Vec<String>>()
388 .join(",")
389 )
390 }
391}
392
393#[cfg(feature = "phf")]
394impl<E: CompileConst> CompileConst for HashSet<E> {
395 fn const_type() -> String {
396 format!("phf::Set<{}>", E::const_type())
397 }
398
399 fn const_val(&self) -> String {
400 format!(
401 "phf::phf_set!{{{}}}",
402 self.iter()
403 .map(|e| e.const_val().to_string())
404 .collect::<Vec<String>>()
405 .join(",")
406 )
407 }
408}
409
410impl CompileConst for Ipv4Addr {
411 fn const_type() -> String {
412 "core::net::Ipv4Addr".to_owned()
413 }
414
415 fn const_val(&self) -> String {
416 format!(
417 "core::net::Ipv4Addr::new({})",
418 self.octets()
419 .iter()
420 .map(|x| x.to_string())
421 .collect::<Vec<String>>()
422 .join(",")
423 )
424 }
425}
426
427impl CompileConst for Ipv6Addr {
428 fn const_type() -> String {
429 "core::net::Ipv6Addr".to_owned()
430 }
431
432 fn const_val(&self) -> String {
433 format!(
434 "core::net::Ipv6Addr::new({})",
435 self.segments()
436 .iter()
437 .map(|x| x.to_string())
438 .collect::<Vec<String>>()
439 .join(",")
440 )
441 }
442}
443
444impl CompileConst for IpAddr {
445 fn const_type() -> String {
446 "core::net::IpAddr".to_owned()
447 }
448
449 fn const_val(&self) -> String {
450 match self {
451 IpAddr::V4(ipv4) => format!("core::net::IpAddr::V4({})", ipv4.const_val()),
452 IpAddr::V6(ipv6) => format!("core::net::IpAddr::V6({})", ipv6.const_val()),
453 }
454 }
455}
456
457impl CompileConst for SocketAddr {
458 fn const_type() -> String {
459 "core::net::SocketAddr".to_owned()
460 }
461
462 fn const_val(&self) -> String {
463 format!(
464 "core::net::SocketAddr::new({}, {})",
465 self.ip().const_val(),
466 self.port()
467 )
468 }
469}
470
471impl CompileConst for SocketAddrV4 {
472 fn const_type() -> String {
473 "core::net::SocketAddrV4".to_owned()
474 }
475
476 fn const_val(&self) -> String {
477 format!(
478 "core::net::SocketAddrV4::new({}, {})",
479 self.ip().const_val(),
480 self.port()
481 )
482 }
483}
484
485impl CompileConst for SocketAddrV6 {
486 fn const_type() -> String {
487 "core::net::SocketAddrV6".to_owned()
488 }
489
490 fn const_val(&self) -> String {
491 format!(
492 "core::net::SocketAddrV6::new({}, {}, {}, {})",
493 self.ip().const_val(),
494 self.port(),
495 self.flowinfo(),
496 self.scope_id()
497 )
498 }
499}
500
501macro_rules! arrays
502{
503 ($($n:literal),*) =>
504 {
505 $(impl<T: CompileConst> CompileConst for [T; $n]
506 {
507 fn const_type() -> String
508 {
509 format!("[{}; {}]", T::const_type(), $n)
510 }
511
512 fn const_val(&self) -> String
513 {
514 format!("[{}]", self
515 .iter()
516 .map(|e| e.const_val())
517 .collect::<Vec<String>>()
518 .join(","))
519 }
520 })*
521 }
522}
523arrays!(
524 0, 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,
525 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
526 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
527 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
528 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
529 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
530 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
531 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
532 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
533 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
534 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
535 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
536 250, 251, 252, 253, 254, 255, 256
537);
538
539macro_rules! tuples
541{
542 ($format:literal $(, $ty:ident $index:tt)*) =>
543 {
544 impl<$($ty: CompileConst),*> CompileConst for ($($ty),*)
545 {
546 fn const_type() -> String
547 {
548 format!($format, $($ty::const_type()),*)
549 }
550
551 fn const_val(&self) -> String
552 {
553 format!($format, $(self.$index.const_val()),*)
554 }
555 }
556
557 impl<$($ty: CompileConstArray),*> CompileConstArray for ($($ty),*)
558 {
559 fn const_array_type(&self) -> String
560 {
561 format!($format, $(self.$index.const_array_type()),*)
562 }
563
564 fn const_array_val(&self) -> String
565 {
566 format!($format, $(self.$index.const_array_val()),*)
567 }
568 }
569 }
570}
571
572tuples!("()");
573tuples!("({},{})", A 0, B 1);
574tuples!("({},{},{})", A 0, B 1, C 2);
575tuples!("({},{},{},{})", A 0, B 1, C 2, D 3);
576tuples!("({},{},{},{},{})", A 0, B 1, C 2, D 3, E 4);
577tuples!("({},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5);
578tuples!("({},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6);
579tuples!("({},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
580tuples!("({},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8);
581tuples!("({},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9);
582tuples!("({},{},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10);
583tuples!("({},{},{},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11);
584tuples!("({},{},{},{},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11, M 12);
585tuples!("({},{},{},{},{},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11, M 12, N 13);
586tuples!("({},{},{},{},{},{},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11, M 12, N 13, O 14);
587tuples!("({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11, M 12, N 13, O 14, P 15);