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 "{}{}{}{}{} {}: {} = {};",
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
501
502macro_rules! arrays
503{
504 ($($n:literal),*) =>
505 {
506 $(impl<T: CompileConst> CompileConst for [T; $n]
507 {
508 fn const_type() -> String
509 {
510 format!("[{}; {}]", T::const_type(), $n)
511 }
512
513 fn const_val(&self) -> String
514 {
515 format!("[{}]", self
516 .iter()
517 .map(|e| e.const_val())
518 .collect::<Vec<String>>()
519 .join(","))
520 }
521 })*
522 }
523}
524arrays!(
525 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,
526 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
527 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
528 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
529 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
530 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
531 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
532 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
533 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
534 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
535 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
536 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
537 250, 251, 252, 253, 254, 255, 256
538);
539
540macro_rules! tuples
542{
543 ($format:literal $(, $ty:ident $index:tt)*) =>
544 {
545 impl<$($ty: CompileConst),*> CompileConst for ($($ty),*)
546 {
547 fn const_type() -> String
548 {
549 format!($format, $($ty::const_type()),*)
550 }
551
552 fn const_val(&self) -> String
553 {
554 format!($format, $(self.$index.const_val()),*)
555 }
556 }
557
558 impl<$($ty: CompileConstArray),*> CompileConstArray for ($($ty),*)
559 {
560 fn const_array_type(&self) -> String
561 {
562 format!($format, $(self.$index.const_array_type()),*)
563 }
564
565 fn const_array_val(&self) -> String
566 {
567 format!($format, $(self.$index.const_array_val()),*)
568 }
569 }
570 }
571}
572
573tuples!("()");
574tuples!("({},{})", A 0, B 1);
575tuples!("({},{},{})", A 0, B 1, C 2);
576tuples!("({},{},{},{})", A 0, B 1, C 2, D 3);
577tuples!("({},{},{},{},{})", A 0, B 1, C 2, D 3, E 4);
578tuples!("({},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5);
579tuples!("({},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6);
580tuples!("({},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7);
581tuples!("({},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8);
582tuples!("({},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9);
583tuples!("({},{},{},{},{},{},{},{},{},{},{})", A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10);
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);
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);
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);
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);
588tuples!("({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{})", 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);