rpgn/
lib.rs

1#![deny(clippy::unwrap_used)]
2#![deny(clippy::expect_used)]
3#![warn(clippy::pedantic)]
4#![warn(clippy::nursery)]
5#![allow(clippy::literal_string_with_formatting_args)]
6#![deny(clippy::unwrap_used, clippy::expect_used)]
7#![allow(clippy::must_use_candidate)]
8#![warn(missing_debug_implementations)]
9#![warn(missing_copy_implementations)]
10#![allow(clippy::module_name_repetitions)]
11#![warn(
12    clippy::arithmetic_side_effects,
13    clippy::unreachable,
14    clippy::unchecked_duration_subtraction,
15    clippy::todo,
16    clippy::string_slice,
17    clippy::panic_in_result_fn,
18    clippy::indexing_slicing,
19    clippy::panic,
20    clippy::exit,
21    clippy::as_conversions,
22    clippy::large_futures,
23    clippy::large_stack_arrays,
24    clippy::large_stack_frames,
25    clippy::modulo_one,
26    clippy::mem_replace_with_uninit,
27    clippy::iterator_step_by_zero,
28    clippy::invalid_regex,
29    clippy::print_stdout,
30    clippy::print_stderr
31)]
32#![doc = include_str!("../README.md")]
33
34mod visitor;
35
36dry_mods::mods! {
37    pub mod eco, date, round;
38    mod pub use
39    eco_category,
40    move_number,
41    outcome,
42    pgn,
43    raw_header_owned,
44    movetext;
45}
46
47pub use date::Date;
48pub use eco::Eco;
49pub use round::Round;
50
51/// These are samples I use in tests and benchmarks.
52/// They're public because benchmarks get the same crate you get.
53#[doc(hidden)]
54pub mod samples;
55pub use movetext::Movetext;
56
57/// Create a [`Variation`](crate::movetext::Variation) out of SAN literals.
58///
59/// # Syntax
60/// See the `samples.rs` file in the repository.
61///
62/// # Panics
63/// See [`SanPlus::from_ascii`](shakmaty::san::SanPlus::from_ascii).
64#[macro_export]
65macro_rules! variation {
66    (_turn: $san:literal) => {
67        $crate::movetext::SanWithVariations { san: ::shakmaty::san::SanPlus::from_ascii($san).unwrap(), variations: vec![] }
68    };
69    (_turn: ($san:literal, [$($vars:tt),+])) => {
70        $crate::movetext::SanWithVariations { san: ::shakmaty::san::SanPlus::from_ascii($san).unwrap(), variations: vec![$($crate::variation! $vars),+] }
71    };
72    {$($turn:tt),+} => {
73        $crate::movetext::Variation(vec![$($crate::variation!(_turn: $turn)),+])
74    };
75}
76
77/// Create a [`Sans`](crate::movetext::Sans) out of a list SAN literals.
78///
79/// # Panics
80/// See [`SanPlus::from_ascii`](shakmaty::san::SanPlus::from_ascii).
81#[macro_export]
82macro_rules! sans {
83    ($($san:literal),+) => {
84        $crate::movetext::Sans(vec![$(::shakmaty::san::SanPlus::from_ascii($san).unwrap()),+])
85    };
86}
87
88#[cfg(feature = "serde")]
89macro_rules! serde_display_from_str {
90    ($type:ident) => {
91        impl serde::Serialize for $type {
92            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
93            where
94                S: serde::Serializer,
95            {
96                serializer.serialize_str(self.to_string().as_str())
97            }
98        }
99
100        impl<'de> serde::Deserialize<'de> for $type {
101            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
102            where
103                D: serde::Deserializer<'de>,
104            {
105                use serde::de::Error;
106                <&str>::deserialize(deserializer)?
107                    .parse()
108                    .map_err(D::Error::custom)
109            }
110        }
111    };
112
113    ($type:ident<$g:ident: Display + FromStr>) => {
114        impl<$g> serde::Serialize for $type<$g>
115        where
116            $g: std::fmt::Display + std::str::FromStr,
117        {
118            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
119            where
120                S: serde::Serializer,
121            {
122                serializer.serialize_str(self.to_string().as_str())
123            }
124        }
125
126        impl<'de, $g> serde::Deserialize<'de> for $type<$g>
127        where
128            $g: std::fmt::Display + std::str::FromStr,
129        {
130            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
131            where
132                D: serde::Deserializer<'de>,
133            {
134                <&str>::deserialize(deserializer)?
135                    .parse()
136                    .map_err(serde::de::Error::custom)
137            }
138        }
139    };
140}
141
142#[cfg(feature = "serde")]
143pub(crate) use serde_display_from_str;