1use crate::symbols::{block, line};
2
3#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
4pub struct Set<'a> {
5 pub top_left: &'a str,
6 pub top_right: &'a str,
7 pub bottom_left: &'a str,
8 pub bottom_right: &'a str,
9 pub vertical_left: &'a str,
10 pub vertical_right: &'a str,
11 pub horizontal_top: &'a str,
12 pub horizontal_bottom: &'a str,
13}
14
15impl Default for Set<'_> {
16 fn default() -> Self {
17 PLAIN
18 }
19}
20
21const fn from_line_set(line_set: line::Set<'_>) -> Set<'_> {
23 Set {
24 top_left: line_set.top_left,
25 top_right: line_set.top_right,
26 bottom_left: line_set.bottom_left,
27 bottom_right: line_set.bottom_right,
28 vertical_left: line_set.vertical,
29 vertical_right: line_set.vertical,
30 horizontal_top: line_set.horizontal,
31 horizontal_bottom: line_set.horizontal,
32 }
33}
34
35pub const PLAIN: Set = Set {
44 top_left: line::NORMAL.top_left,
45 top_right: line::NORMAL.top_right,
46 bottom_left: line::NORMAL.bottom_left,
47 bottom_right: line::NORMAL.bottom_right,
48 vertical_left: line::NORMAL.vertical,
49 vertical_right: line::NORMAL.vertical,
50 horizontal_top: line::NORMAL.horizontal,
51 horizontal_bottom: line::NORMAL.horizontal,
52};
53
54pub const ROUNDED: Set = Set {
63 top_left: line::ROUNDED.top_left,
64 top_right: line::ROUNDED.top_right,
65 bottom_left: line::ROUNDED.bottom_left,
66 bottom_right: line::ROUNDED.bottom_right,
67 vertical_left: line::ROUNDED.vertical,
68 vertical_right: line::ROUNDED.vertical,
69 horizontal_top: line::ROUNDED.horizontal,
70 horizontal_bottom: line::ROUNDED.horizontal,
71};
72
73pub const DOUBLE: Set = Set {
82 top_left: line::DOUBLE.top_left,
83 top_right: line::DOUBLE.top_right,
84 bottom_left: line::DOUBLE.bottom_left,
85 bottom_right: line::DOUBLE.bottom_right,
86 vertical_left: line::DOUBLE.vertical,
87 vertical_right: line::DOUBLE.vertical,
88 horizontal_top: line::DOUBLE.horizontal,
89 horizontal_bottom: line::DOUBLE.horizontal,
90};
91
92pub const THICK: Set = Set {
101 top_left: line::THICK.top_left,
102 top_right: line::THICK.top_right,
103 bottom_left: line::THICK.bottom_left,
104 bottom_right: line::THICK.bottom_right,
105 vertical_left: line::THICK.vertical,
106 vertical_right: line::THICK.vertical,
107 horizontal_top: line::THICK.horizontal,
108 horizontal_bottom: line::THICK.horizontal,
109};
110
111pub const LIGHT_DOUBLE_DASHED: Set = from_line_set(line::LIGHT_DOUBLE_DASHED);
120
121pub const HEAVY_DOUBLE_DASHED: Set = from_line_set(line::HEAVY_DOUBLE_DASHED);
130
131pub const LIGHT_TRIPLE_DASHED: Set = from_line_set(line::LIGHT_TRIPLE_DASHED);
140
141pub const HEAVY_TRIPLE_DASHED: Set = from_line_set(line::HEAVY_TRIPLE_DASHED);
150
151pub const LIGHT_QUADRUPLE_DASHED: Set = from_line_set(line::LIGHT_QUADRUPLE_DASHED);
160
161pub const HEAVY_QUADRUPLE_DASHED: Set = from_line_set(line::HEAVY_QUADRUPLE_DASHED);
170
171pub const QUADRANT_TOP_LEFT: &str = "▘";
172pub const QUADRANT_TOP_RIGHT: &str = "▝";
173pub const QUADRANT_BOTTOM_LEFT: &str = "▖";
174pub const QUADRANT_BOTTOM_RIGHT: &str = "▗";
175pub const QUADRANT_TOP_HALF: &str = "▀";
176pub const QUADRANT_BOTTOM_HALF: &str = "▄";
177pub const QUADRANT_LEFT_HALF: &str = "▌";
178pub const QUADRANT_RIGHT_HALF: &str = "▐";
179pub const QUADRANT_TOP_LEFT_BOTTOM_LEFT_BOTTOM_RIGHT: &str = "▙";
180pub const QUADRANT_TOP_LEFT_TOP_RIGHT_BOTTOM_LEFT: &str = "▛";
181pub const QUADRANT_TOP_LEFT_TOP_RIGHT_BOTTOM_RIGHT: &str = "▜";
182pub const QUADRANT_TOP_RIGHT_BOTTOM_LEFT_BOTTOM_RIGHT: &str = "▟";
183pub const QUADRANT_TOP_LEFT_BOTTOM_RIGHT: &str = "▚";
184pub const QUADRANT_TOP_RIGHT_BOTTOM_LEFT: &str = "▞";
185pub const QUADRANT_BLOCK: &str = "█";
186
187pub const QUADRANT_OUTSIDE: Set = Set {
196 top_left: QUADRANT_TOP_LEFT_TOP_RIGHT_BOTTOM_LEFT,
197 top_right: QUADRANT_TOP_LEFT_TOP_RIGHT_BOTTOM_RIGHT,
198 bottom_left: QUADRANT_TOP_LEFT_BOTTOM_LEFT_BOTTOM_RIGHT,
199 bottom_right: QUADRANT_TOP_RIGHT_BOTTOM_LEFT_BOTTOM_RIGHT,
200 vertical_left: QUADRANT_LEFT_HALF,
201 vertical_right: QUADRANT_RIGHT_HALF,
202 horizontal_top: QUADRANT_TOP_HALF,
203 horizontal_bottom: QUADRANT_BOTTOM_HALF,
204};
205
206pub const QUADRANT_INSIDE: Set = Set {
215 top_right: QUADRANT_BOTTOM_LEFT,
216 top_left: QUADRANT_BOTTOM_RIGHT,
217 bottom_right: QUADRANT_TOP_LEFT,
218 bottom_left: QUADRANT_TOP_RIGHT,
219 vertical_left: QUADRANT_RIGHT_HALF,
220 vertical_right: QUADRANT_LEFT_HALF,
221 horizontal_top: QUADRANT_BOTTOM_HALF,
222 horizontal_bottom: QUADRANT_TOP_HALF,
223};
224
225pub const ONE_EIGHTH_TOP_EIGHT: &str = "▔";
226pub const ONE_EIGHTH_BOTTOM_EIGHT: &str = "▁";
227pub const ONE_EIGHTH_LEFT_EIGHT: &str = "▏";
228pub const ONE_EIGHTH_RIGHT_EIGHT: &str = "▕";
229
230#[expect(clippy::doc_markdown)]
239pub const ONE_EIGHTH_WIDE: Set = Set {
240 top_right: ONE_EIGHTH_BOTTOM_EIGHT,
241 top_left: ONE_EIGHTH_BOTTOM_EIGHT,
242 bottom_right: ONE_EIGHTH_TOP_EIGHT,
243 bottom_left: ONE_EIGHTH_TOP_EIGHT,
244 vertical_left: ONE_EIGHTH_LEFT_EIGHT,
245 vertical_right: ONE_EIGHTH_RIGHT_EIGHT,
246 horizontal_top: ONE_EIGHTH_BOTTOM_EIGHT,
247 horizontal_bottom: ONE_EIGHTH_TOP_EIGHT,
248};
249
250#[expect(clippy::doc_markdown)]
259pub const ONE_EIGHTH_TALL: Set = Set {
260 top_right: ONE_EIGHTH_LEFT_EIGHT,
261 top_left: ONE_EIGHTH_RIGHT_EIGHT,
262 bottom_right: ONE_EIGHTH_LEFT_EIGHT,
263 bottom_left: ONE_EIGHTH_RIGHT_EIGHT,
264 vertical_left: ONE_EIGHTH_RIGHT_EIGHT,
265 vertical_right: ONE_EIGHTH_LEFT_EIGHT,
266 horizontal_top: ONE_EIGHTH_TOP_EIGHT,
267 horizontal_bottom: ONE_EIGHTH_BOTTOM_EIGHT,
268};
269
270pub const PROPORTIONAL_WIDE: Set = Set {
282 top_right: QUADRANT_BOTTOM_HALF,
283 top_left: QUADRANT_BOTTOM_HALF,
284 bottom_right: QUADRANT_TOP_HALF,
285 bottom_left: QUADRANT_TOP_HALF,
286 vertical_left: QUADRANT_BLOCK,
287 vertical_right: QUADRANT_BLOCK,
288 horizontal_top: QUADRANT_BOTTOM_HALF,
289 horizontal_bottom: QUADRANT_TOP_HALF,
290};
291
292pub const PROPORTIONAL_TALL: Set = Set {
304 top_right: QUADRANT_BLOCK,
305 top_left: QUADRANT_BLOCK,
306 bottom_right: QUADRANT_BLOCK,
307 bottom_left: QUADRANT_BLOCK,
308 vertical_left: QUADRANT_BLOCK,
309 vertical_right: QUADRANT_BLOCK,
310 horizontal_top: QUADRANT_TOP_HALF,
311 horizontal_bottom: QUADRANT_BOTTOM_HALF,
312};
313
314pub const FULL: Set = Set {
325 top_left: block::FULL,
326 top_right: block::FULL,
327 bottom_left: block::FULL,
328 bottom_right: block::FULL,
329 vertical_left: block::FULL,
330 vertical_right: block::FULL,
331 horizontal_top: block::FULL,
332 horizontal_bottom: block::FULL,
333};
334
335pub const EMPTY: Set = Set {
356 top_left: " ",
357 top_right: " ",
358 bottom_left: " ",
359 bottom_right: " ",
360 vertical_left: " ",
361 vertical_right: " ",
362 horizontal_top: " ",
363 horizontal_bottom: " ",
364};
365
366#[cfg(test)]
367mod tests {
368 use alloc::format;
369 use alloc::string::String;
370
371 use indoc::{formatdoc, indoc};
372
373 use super::*;
374
375 #[test]
376 fn default() {
377 assert_eq!(Set::default(), PLAIN);
378 }
379
380 fn render(set: Set) -> String {
385 formatdoc!(
386 "░░░░░░
387 ░{}{}{}{}░
388 ░{}░░{}░
389 ░{}░░{}░
390 ░{}{}{}{}░
391 ░░░░░░",
392 set.top_left,
393 set.horizontal_top,
394 set.horizontal_top,
395 set.top_right,
396 set.vertical_left,
397 set.vertical_right,
398 set.vertical_left,
399 set.vertical_right,
400 set.bottom_left,
401 set.horizontal_bottom,
402 set.horizontal_bottom,
403 set.bottom_right
404 )
405 }
406
407 #[test]
408 fn border_set_from_line_set() {
409 let custom_line_set = line::Set {
410 top_left: "a",
411 top_right: "b",
412 bottom_left: "c",
413 bottom_right: "d",
414 vertical: "e",
415 horizontal: "f",
416 vertical_left: "g",
417 vertical_right: "h",
418 horizontal_down: "i",
419 horizontal_up: "j",
420 cross: "k",
421 };
422
423 let border_set = from_line_set(custom_line_set);
424
425 assert_eq!(
426 border_set,
427 Set {
428 top_left: "a",
429 top_right: "b",
430 bottom_left: "c",
431 bottom_right: "d",
432 vertical_left: "e",
433 vertical_right: "e",
434 horizontal_bottom: "f",
435 horizontal_top: "f",
436 }
437 );
438 }
439
440 #[test]
441 fn plain() {
442 assert_eq!(
443 render(PLAIN),
444 indoc!(
445 "░░░░░░
446 ░┌──┐░
447 ░│░░│░
448 ░│░░│░
449 ░└──┘░
450 ░░░░░░"
451 )
452 );
453 }
454
455 #[test]
456 fn rounded() {
457 assert_eq!(
458 render(ROUNDED),
459 indoc!(
460 "░░░░░░
461 ░╭──╮░
462 ░│░░│░
463 ░│░░│░
464 ░╰──╯░
465 ░░░░░░"
466 )
467 );
468 }
469
470 #[test]
471 fn double() {
472 assert_eq!(
473 render(DOUBLE),
474 indoc!(
475 "░░░░░░
476 ░╔══╗░
477 ░║░░║░
478 ░║░░║░
479 ░╚══╝░
480 ░░░░░░"
481 )
482 );
483 }
484
485 #[test]
486 fn thick() {
487 assert_eq!(
488 render(THICK),
489 indoc!(
490 "░░░░░░
491 ░┏━━┓░
492 ░┃░░┃░
493 ░┃░░┃░
494 ░┗━━┛░
495 ░░░░░░"
496 )
497 );
498 }
499
500 #[test]
501 fn light_double_dashed() {
502 assert_eq!(
503 render(LIGHT_DOUBLE_DASHED),
504 indoc!(
505 "░░░░░░
506 ░┌╌╌┐░
507 ░╎░░╎░
508 ░╎░░╎░
509 ░└╌╌┘░
510 ░░░░░░"
511 )
512 );
513 }
514
515 #[test]
516 fn heavy_double_dashed() {
517 assert_eq!(
518 render(HEAVY_DOUBLE_DASHED),
519 indoc!(
520 "░░░░░░
521 ░┏╍╍┓░
522 ░╏░░╏░
523 ░╏░░╏░
524 ░┗╍╍┛░
525 ░░░░░░"
526 )
527 );
528 }
529
530 #[test]
531 fn light_triple_dashed() {
532 assert_eq!(
533 render(LIGHT_TRIPLE_DASHED),
534 indoc!(
535 "░░░░░░
536 ░┌┄┄┐░
537 ░┆░░┆░
538 ░┆░░┆░
539 ░└┄┄┘░
540 ░░░░░░"
541 )
542 );
543 }
544
545 #[test]
546 fn heavy_triple_dashed() {
547 assert_eq!(
548 render(HEAVY_TRIPLE_DASHED),
549 indoc!(
550 "░░░░░░
551 ░┏┅┅┓░
552 ░┇░░┇░
553 ░┇░░┇░
554 ░┗┅┅┛░
555 ░░░░░░"
556 )
557 );
558 }
559
560 #[test]
561 fn light_quadruple_dashed() {
562 assert_eq!(
563 render(LIGHT_QUADRUPLE_DASHED),
564 indoc!(
565 "░░░░░░
566 ░┌┈┈┐░
567 ░┊░░┊░
568 ░┊░░┊░
569 ░└┈┈┘░
570 ░░░░░░"
571 )
572 );
573 }
574
575 #[test]
576 fn heavy_quadruple_dashed() {
577 assert_eq!(
578 render(HEAVY_QUADRUPLE_DASHED),
579 indoc!(
580 "░░░░░░
581 ░┏┉┉┓░
582 ░┋░░┋░
583 ░┋░░┋░
584 ░┗┉┉┛░
585 ░░░░░░"
586 )
587 );
588 }
589
590 #[test]
591 fn quadrant_outside() {
592 assert_eq!(
593 render(QUADRANT_OUTSIDE),
594 indoc!(
595 "░░░░░░
596 ░▛▀▀▜░
597 ░▌░░▐░
598 ░▌░░▐░
599 ░▙▄▄▟░
600 ░░░░░░"
601 )
602 );
603 }
604
605 #[test]
606 fn quadrant_inside() {
607 assert_eq!(
608 render(QUADRANT_INSIDE),
609 indoc!(
610 "░░░░░░
611 ░▗▄▄▖░
612 ░▐░░▌░
613 ░▐░░▌░
614 ░▝▀▀▘░
615 ░░░░░░"
616 )
617 );
618 }
619
620 #[test]
621 fn one_eighth_wide() {
622 assert_eq!(
623 render(ONE_EIGHTH_WIDE),
624 indoc!(
625 "░░░░░░
626 ░▁▁▁▁░
627 ░▏░░▕░
628 ░▏░░▕░
629 ░▔▔▔▔░
630 ░░░░░░"
631 )
632 );
633 }
634
635 #[test]
636 fn one_eighth_tall() {
637 assert_eq!(
638 render(ONE_EIGHTH_TALL),
639 indoc!(
640 "░░░░░░
641 ░▕▔▔▏░
642 ░▕░░▏░
643 ░▕░░▏░
644 ░▕▁▁▏░
645 ░░░░░░"
646 )
647 );
648 }
649
650 #[test]
651 fn proportional_wide() {
652 assert_eq!(
653 render(PROPORTIONAL_WIDE),
654 indoc!(
655 "░░░░░░
656 ░▄▄▄▄░
657 ░█░░█░
658 ░█░░█░
659 ░▀▀▀▀░
660 ░░░░░░"
661 )
662 );
663 }
664
665 #[test]
666 fn proportional_tall() {
667 assert_eq!(
668 render(PROPORTIONAL_TALL),
669 indoc!(
670 "░░░░░░
671 ░█▀▀█░
672 ░█░░█░
673 ░█░░█░
674 ░█▄▄█░
675 ░░░░░░"
676 )
677 );
678 }
679
680 #[test]
681 fn full() {
682 assert_eq!(
683 render(FULL),
684 indoc!(
685 "░░░░░░
686 ░████░
687 ░█░░█░
688 ░█░░█░
689 ░████░
690 ░░░░░░"
691 )
692 );
693 }
694
695 #[test]
696 fn empty() {
697 assert_eq!(
698 render(EMPTY),
699 indoc!(
700 "░░░░░░
701 ░ ░
702 ░ ░░ ░
703 ░ ░░ ░
704 ░ ░
705 ░░░░░░"
706 )
707 );
708 }
709}