1use itertools::Itertools;
2use nom::branch::*;
3use nom::bytes::complete::tag;
4use nom::character::complete;
5use nom::combinator::*;
6use nom::error::context;
7use nom::multi::*;
8use nom::sequence::*;
9
10use crate::parser::parsers::{Elms, ipv4_address_parsers, UResult};
11use crate::parser::parsers::basic_parsers::*;
12
13#[inline]
14pub(crate) fn h16(i: Elms) -> UResult<Elms, String> {
15 context(
16 "h16",
17 map(many_m_n(1, 4, hex_digit), |sl| sl.into_iter().collect()),
18 )(i)
19}
20
21#[inline]
22pub(crate) fn ls32(i: Elms) -> UResult<Elms, String> {
23 context(
24 "ls32",
25 alt((
26 map(
27 tuple((h16, preceded(complete::char(':'), h16))),
28 |(c1, c2)| [c1, c2].join(":"),
29 ),
30 ipv4_address_parsers::ipv4_address,
31 )),
32 )(i)
33}
34
35#[inline]
37pub(crate) fn ipv6_address1(i: Elms) -> UResult<Elms, String> {
38 context(
39 "ipv6_address1",
40 map(
41 tuple((
42 map(count(terminated(h16, complete::char(':')), 6), |sl| {
43 sl.iter().join(":")
44 }),
45 ls32,
46 )),
47 |(s1, s2)| [s1, s2].join(":"),
48 ),
49 )(i)
50}
51
52#[inline]
54pub(crate) fn ipv6_address2(i: Elms) -> UResult<Elms, String> {
55 context(
56 "ipv6_address2",
57 map(
58 tuple((
59 preceded(
60 tag("::"),
61 map(count(terminated(h16, tag(":")), 5), |sl| sl.join(":")),
62 ),
63 ls32,
64 )),
65 |(b, c)| format!("::{}:{}", b, c),
66 ),
67 )(i)
68}
69
70#[inline]
72pub(crate) fn ipv6_address3(i: Elms) -> UResult<Elms, String> {
73 context(
74 "ipv6_address3",
75 map(
76 tuple((
77 terminated(opt(h16), tag("::")),
78 map(
79 count(
80 map(terminated(h16, complete::char(':')), |s| format!("{}:", s)),
81 4,
82 ),
83 |sl| sl.into_iter().collect::<String>(),
84 ),
85 ls32,
86 )),
87 |(s1, s2, s3)| format!("{}::{}{}", s1.unwrap_or("".to_string()), s2, s3),
88 ),
89 )(i)
90}
91
92#[inline]
93fn ipv6_address_<'a>(n1: usize, n2: usize) -> impl FnMut(Elms<'a>) -> UResult<Elms<'a>, String> {
94 let h16_with_colon = || {
95 map(tuple((h16, complete::char(':'))), |(s, c)| {
96 format!("{}{}", s, c)
97 })
98 };
99 let colon_with_h16 = || {
100 map(tuple((complete::char(':'), h16)), |(c, s)| {
101 format!("{}{}", c, s)
102 })
103 };
104 map(
105 tuple((
106 terminated(
107 map(
108 opt(map(
109 tuple((h16, many_m_n(0, n1, colon_with_h16()))),
110 |(s1, s2)| format!("{}{}", s1, s2.into_iter().collect::<String>()),
111 )),
112 |v| v.unwrap_or("".to_string()),
113 ),
114 tag("::"),
115 ),
116 count(h16_with_colon(), n2),
117 ls32,
118 )),
119 |(s1, s2, s3)| format!("{}::{}{}", s1, s2.into_iter().collect::<String>(), s3),
120 )
121}
122
123#[inline]
126pub(crate) fn ipv6_address4(i: Elms) -> UResult<Elms, String> {
127 context("ipv6_address4", ipv6_address_(1, 3))(i)
128}
129
130#[inline]
133pub(crate) fn ipv6_address5(i: Elms) -> UResult<Elms, String> {
134 context("ipv6_address5", ipv6_address_(2, 2))(i)
135}
136
137#[inline]
140pub(crate) fn ipv6_address6(i: Elms) -> UResult<Elms, String> {
141 context("ipv6_address6", ipv6_address_(3, 1))(i)
142}
143
144#[inline]
147pub(crate) fn ipv6_address7(i: Elms) -> UResult<Elms, String> {
148 context(
149 "ipv6_address7",
150 map(
151 tuple((
152 terminated(
153 map(
154 opt(map(
155 tuple((
156 h16,
157 many_m_n(
158 0,
159 4,
160 map(preceded(complete::char(':'), h16), |s| format!(":{}", s)),
161 ),
162 )),
163 |(s1, s2)| format!("{}{}", s1, s2.into_iter().collect::<String>()),
164 )),
165 |v| v.unwrap_or("".to_string()),
166 ),
167 tag("::"),
168 ),
169 ls32,
170 )),
171 |(s1, s2)| [s1, s2].join("::"),
172 ),
173 )(i)
174}
175
176#[inline]
179pub(crate) fn ipv6_address8(i: Elms) -> UResult<Elms, String> {
180 context(
181 "ipv6_address8",
182 map(
183 tuple((
184 terminated(
185 map(
186 opt(map(
187 tuple((
188 h16,
189 many_m_n(
190 0,
191 5,
192 map(preceded(complete::char(':'), h16), |s| format!(":{}", s)),
193 ),
194 )),
195 |(s1, s2)| format!("{}{}", s1, s2.into_iter().collect::<String>()),
196 )),
197 |v| v.unwrap_or("".to_string()),
198 ),
199 tag("::"),
200 ),
201 h16,
202 )),
203 |(s1, s2)| [s1, s2].join("::"),
204 ),
205 )(i)
206}
207
208#[inline]
211pub(crate) fn ipv6_address9(i: Elms) -> UResult<Elms, String> {
212 context(
213 "ipv6_address9",
214 map(
215 tuple((
216 map(
217 opt(map(
218 tuple((
219 h16,
220 many_m_n(
221 0,
222 6,
223 map(tuple((complete::char(':'), h16)), |(c, s)| {
224 let mut r = String::new();
225 r.push(c);
226 r.push_str(&s);
227 r
228 }),
229 ),
230 )),
231 |(s1, s2)| [s1, s2.join("")].join(""),
232 )),
233 |v: Option<String>| v.unwrap_or("".to_string()),
234 ),
235 tag("::"),
236 )),
237 |(s1, s2): (String, Elms)| s1 + s2.as_str().unwrap(),
238 ),
239 )(i)
240}
241
242#[inline]
243pub fn ipv6_address(i: Elms) -> UResult<Elms, String> {
244 context(
245 "ipv6_address",
246 alt((
247 ipv6_address1,
248 ipv6_address2,
249 ipv6_address3,
250 ipv6_address4,
251 ipv6_address5,
252 ipv6_address6,
253 ipv6_address7,
254 ipv6_address8,
255 ipv6_address9,
256 )),
257 )(i)
258}
259
260#[cfg(test)]
261pub mod gens {
262 use itertools::Itertools;
263 use prop_check_rs::gen::{Gen, Gens};
264
265 use crate::parser::parsers::ipv4_address_parsers::gens::*;
266 use crate::parser::parsers::basic_parsers::gens::*;
267
268 pub fn h16_gen() -> Gen<String> {
269 Gens::choose_u8(1, 4).bind(|n| rep_char_gen(n, || hex_digit_char_gen()))
270 }
271
272 pub fn ls32_gen() -> Gen<String> {
273 Gens::choose_u8(1, 2).bind(|n| match n {
274 1 => ipv4_address_str_gen(),
275 2 => Gens::list_of_n(2, || h16_gen()).fmap(|sl| sl.join(":")),
276 x => panic!("x = {}", x),
277 })
278 }
279 pub fn ipv6_address_gen1() -> Gen<String> {
280 Gens::list_of_n(6, || h16_gen())
281 .bind(|sl| ls32_gen().fmap(move |ls32| format!("{}:{}", sl.join(":"), ls32)))
282 }
283
284 pub fn ipv6_address_gen2() -> Gen<String> {
285 Gens::list_of_n(5, || h16_gen())
286 .bind(|sl| ls32_gen().fmap(move |ls32| format!("::{}:{}", sl.join(":"), ls32)))
287 }
288
289 pub fn ipv6_address_gen3() -> Gen<String> {
290 Gens::list_of_n(5, || h16_gen()).bind(|sl| {
291 ls32_gen().fmap(move |ls32| {
292 let (h, t) = sl.split_first().unwrap();
293 format!("{}::{}:{}", h, t.join(":"), ls32)
294 })
295 })
296 }
297
298 pub fn ipv6_address_gen4() -> Gen<String> {
300 Gens::one_bool()
301 .bind(|b| {
302 if b {
303 Gens::choose_u8(1, 2).bind(|n| match n {
304 1 => h16_gen(),
305 2 => Gens::list_of_n(2, || h16_gen()).fmap(|sl| sl.join(":")),
306 x => panic!("x = {}", x),
307 })
308 } else {
309 Gen::<String>::unit(|| "".to_string())
310 }
311 })
312 .bind(|s0| {
313 Gens::list_of_n(3, || h16_gen().fmap(|v| format!("{}:", v)))
314 .fmap(|sl| sl.iter().join(""))
315 .fmap(|s| format!("::{}", s))
316 .bind(|s2| ls32_gen().fmap(move |s3| format!("{}{}", s2, s3)))
317 .fmap(move |s| format!("{}{}", s0, s))
318 })
319 }
320
321 pub fn ipv6_address_gen5() -> Gen<String> {
323 Gens::one_bool()
324 .bind(|b| {
325 if b {
326 Gens::choose_u8(1, 2).bind(|n| match n {
327 1 => h16_gen(),
328 2 => Gens::list_of_n(3, || h16_gen()).fmap(|sl| sl.join(":")),
329 x => panic!("x = {}", x),
330 })
331 } else {
332 Gen::<String>::unit(|| "".to_string())
333 }
334 })
335 .bind(|s0| {
336 Gens::list_of_n(2, || h16_gen().fmap(|v| format!("{}:", v)))
337 .fmap(|sl| sl.iter().join(""))
338 .fmap(|s| format!("::{}", s))
339 .bind(|s2| ls32_gen().fmap(move |s3| format!("{}{}", s2, s3)))
340 .fmap(move |s| format!("{}{}", s0, s))
341 })
342 }
343
344 pub fn ipv6_address_gen6() -> Gen<String> {
346 Gens::one_bool()
347 .bind(|b| {
348 if b {
349 Gens::choose_u8(1, 2).bind(|n| match n {
350 1 => h16_gen(),
351 2 => Gens::list_of_n(3, || h16_gen()).fmap(|sl| sl.join(":")),
352 x => panic!("x = {}", x),
353 })
354 } else {
355 Gen::<String>::unit(|| "".to_string())
356 }
357 })
358 .bind(|s0| {
359 Gens::list_of_n(1, || h16_gen().fmap(|v| format!("{}:", v)))
360 .fmap(|sl| sl.join(""))
361 .fmap(|s| format!("::{}", s))
362 .bind(|s2| ls32_gen().fmap(move |s3| format!("{}{}", s2, s3)))
363 .fmap(move |s| format!("{}{}", s0, s))
364 })
365 }
366
367 pub fn ipv6_address_gen7() -> Gen<String> {
369 Gens::one_bool()
370 .bind(|b| {
371 if b {
372 Gens::choose_u8(1, 2).bind(|n| match n {
373 1 => h16_gen(),
374 2 => Gens::list_of_n(4, || h16_gen()).fmap(|sl| sl.join(":")),
375 x => panic!("x = {}", x),
376 })
377 } else {
378 Gen::<String>::unit(|| "".to_string())
379 }
380 })
381 .bind(|s0| ls32_gen().fmap(move |s1| format!("{}::{}", s0, s1)))
382 }
383
384 pub fn ipv6_address_gen8() -> Gen<String> {
386 Gens::one_bool()
387 .bind(|b| {
388 if b {
389 Gens::choose_u8(1, 2).bind(|n| match n {
390 1 => h16_gen(),
391 2 => Gens::list_of_n(5, || h16_gen()).fmap(|sl| sl.join(":")),
392 x => panic!("x = {}", x),
393 })
394 } else {
395 Gen::<String>::unit(|| "".to_string())
396 }
397 })
398 .bind(|s0| h16_gen().fmap(move |s1| format!("{}::{}", s0, s1)))
399 }
400
401 pub fn ipv6_address_gen9() -> Gen<String> {
403 Gens::one_bool()
404 .bind(|b| {
405 if b {
406 Gens::choose_u8(1, 2).bind(|n| match n {
407 1 => h16_gen(),
408 2 => Gens::list_of_n(6, || h16_gen()).fmap(|sl| sl.join(":")),
409 x => panic!("x = {}", x),
410 })
411 } else {
412 Gen::<String>::unit(|| "".to_string())
413 }
414 })
415 .fmap(|s0| format!("{}::", s0))
416 }
417
418 pub fn ipv6_address_str_gen() -> Gen<String> {
419 Gens::choose_u8(1, 9).bind(|n| match n {
420 1 => ipv6_address_gen1(),
421 2 => ipv6_address_gen2(),
422 3 => ipv6_address_gen3(),
423 4 => ipv6_address_gen4(),
424 5 => ipv6_address_gen5(),
425 6 => ipv6_address_gen6(),
426 7 => ipv6_address_gen7(),
427 8 => ipv6_address_gen8(),
428 9 => ipv6_address_gen9(),
429 x => panic!("x = {}", x),
430 })
431 }
432}
433
434#[cfg(test)]
435mod test {
436 use std::env;
437
438 use anyhow::Result;
439
440 use prop_check_rs::prop;
441 use prop_check_rs::prop::TestCases;
442 use prop_check_rs::rng::RNG;
443
444 use super::*;
445 use super::gens::*;
446
447 const TEST_COUNT: TestCases = 100;
448
449 fn init() {
450 env::set_var("RUST_LOG", "debug");
451 let _ = env_logger::builder().is_test(true).try_init();
452 }
453
454 #[test]
455 fn test_h16() -> Result<()> {
456 init();
457 let mut counter = 0;
458 let prop = prop::for_all(
459 || h16_gen(),
460 move |s| {
461 counter += 1;
462 log::debug!("{:>03}, h16 = {}", counter, s);
463 let (_, r) = h16(Elms::new(s.as_bytes())).ok().unwrap();
464 assert_eq!(r, s);
465 true
466 },
467 );
468 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
469 }
470
471 #[test]
472 fn test_ls32() -> Result<()> {
473 init();
474 let mut counter = 0;
475 let prop = prop::for_all(
476 || ls32_gen(),
477 move |s| {
478 counter += 1;
479 log::debug!("{:>03}, ls32 = {}", counter, s);
480 let (_, r) = ls32(Elms::new(s.as_bytes())).ok().unwrap();
481 assert_eq!(r, s);
482 true
483 },
484 );
485 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
486 }
487
488 #[test]
489 fn test_ipv6_address1() -> Result<()> {
490 init();
491 let mut counter = 0;
492 let prop = prop::for_all(
493 || ipv6_address_gen1(),
494 move |s| {
495 counter += 1;
496 log::debug!("{:>03}, ipv6_address1 = {}", counter, s);
497 let (_, r) = ipv6_address1(Elms::new(s.as_bytes())).ok().unwrap();
498 assert_eq!(r, s);
499 true
500 },
501 );
502 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
503 }
504
505 #[test]
506 fn test_ipv6_address2() -> Result<()> {
507 init();
508 let mut counter = 0;
509 let prop = prop::for_all(
510 || ipv6_address_gen2(),
511 move |s| {
512 counter += 1;
513 log::debug!("{:>03}, ipv6_address2 = {}", counter, s);
514 let (_, r) = ipv6_address2(Elms::new(s.as_bytes())).ok().unwrap();
515 assert_eq!(r, s);
516 true
517 },
518 );
519 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
520 }
521
522 #[test]
523 fn test_ipv6_address3() -> Result<()> {
524 init();
525 let mut counter = 0;
526 let prop = prop::for_all(
527 || ipv6_address_gen3(),
528 move |s| {
529 counter += 1;
530 log::debug!("{:>03}, ipv6_address3 = {}", counter, s);
531 let (_, r) = ipv6_address3(Elms::new(s.as_bytes())).ok().unwrap();
532 assert_eq!(r, s);
533 true
534 },
535 );
536 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
537 }
538
539 #[test]
540 fn test_ipv6_address4() -> Result<()> {
541 init();
542 let mut counter = 0;
543 let prop = prop::for_all(
544 || ipv6_address_gen4(),
545 move |s| {
546 counter += 1;
547 log::debug!("{:>03}, ipv6_address4 = {}", counter, s);
548 let r = ipv6_address4(Elms::new(s.as_bytes()));
549 let (_, r) = r.ok().unwrap();
550 assert_eq!(r, s);
551 true
552 },
553 );
554 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
555 }
556
557 #[test]
558 fn test_ipv6_address5() -> Result<()> {
559 init();
560 let mut counter = 0;
561 let prop = prop::for_all(
562 || ipv6_address_gen5(),
563 move |s| {
564 counter += 1;
565 log::debug!("{:>03}, ipv6_address5 = {}", counter, s);
566 let (_, r) = ipv6_address5(Elms::new(s.as_bytes())).ok().unwrap();
567 assert_eq!(r, s);
568 true
569 },
570 );
571 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
572 }
573
574 #[test]
575 fn test_ipv6_address6() -> Result<()> {
576 init();
577 let mut counter = 0;
578 let prop = prop::for_all(
579 || ipv6_address_gen6(),
580 move |s| {
581 counter += 1;
582 log::debug!("{:>03}, ipv6_address6 = {}", counter, s);
583 let (_, r) = ipv6_address6(Elms::new(s.as_bytes())).ok().unwrap();
584 assert_eq!(r, s);
585 true
586 },
587 );
588 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
589 }
590
591 #[test]
592 fn test_ipv6_address7() -> Result<()> {
593 init();
594 let mut counter = 0;
595 let prop = prop::for_all(
596 || ipv6_address_gen7(),
597 move |s| {
598 counter += 1;
599 log::debug!("{:>03}, ipv6_address7 = {}", counter, s);
600 let (_, r) = ipv6_address7(Elms::new(s.as_bytes())).ok().unwrap();
601 assert_eq!(r, s);
602 true
603 },
604 );
605 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
606 }
607
608 #[test]
609 fn test_ipv6_address8() -> Result<()> {
610 init();
611 let mut counter = 0;
612 let prop = prop::for_all(
613 || ipv6_address_gen8(),
614 move |s| {
615 counter += 1;
616 log::debug!("{:>03}, ipv6_address8 = {}", counter, s);
617 let (_, r) = ipv6_address8(Elms::new(s.as_bytes())).ok().unwrap();
618 assert_eq!(r, s);
619 true
620 },
621 );
622 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
623 }
624
625 #[test]
626 fn test_ipv6_address9() -> Result<()> {
627 init();
628 let mut counter = 0;
629 let prop = prop::for_all(
630 || ipv6_address_gen9(),
631 move |s| {
632 counter += 1;
633 log::debug!("{:>03}, ipv6_address9 = {}", counter, s);
634 let (_, r) = ipv6_address9(Elms::new(s.as_bytes())).ok().unwrap();
635 assert_eq!(r, s);
636 true
637 },
638 );
639 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
640 }
641
642 #[test]
643 fn test_ipv6_address() -> Result<()> {
644 init();
645 let mut counter = 0;
646 let prop = prop::for_all(
647 || ipv6_address_str_gen(),
648 move |s| {
649 counter += 1;
650 log::debug!("{:>03}, ipv6_address = {}", counter, s);
651 let (_, r) = ipv6_address(Elms::new(s.as_bytes())).ok().unwrap();
652 assert_eq!(r, s);
653 true
654 },
655 );
656 prop::test_with_prop(prop, 5, TEST_COUNT, RNG::new())
657 }
658}