1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![cfg_attr(docsrs, allow(unused_attributes))]
5#![deny(missing_docs)]
6#![forbid(unsafe_code)]
7
8#[cfg(feature = "ontology")]
9#[cfg_attr(docsrs, doc(cfg(feature = "ontology")))]
10pub mod ontology;
11
12#[cfg(feature = "rated")]
13#[cfg_attr(docsrs, doc(cfg(feature = "rated")))]
14pub mod rated;
15
16#[cfg(feature = "ontology")]
17#[cfg_attr(docsrs, doc(cfg(feature = "ontology")))]
18pub use ontology::SoundEvent;
19
20#[cfg(feature = "rated")]
21#[cfg_attr(docsrs, doc(cfg(feature = "rated")))]
22pub use rated::RatedSoundEvent;
23
24#[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
26#[error("unknown restriction: {0}")]
27pub struct UnknownRestriction<'a>(&'a str);
28
29impl<'a> UnknownRestriction<'a> {
30 #[cfg_attr(not(tarpaulin), inline(always))]
32 pub const fn name(&self) -> &'a str {
33 self.0
34 }
35}
36
37impl<'a> TryFrom<&'a str> for Restriction {
38 type Error = UnknownRestriction<'a>;
39
40 #[cfg_attr(not(tarpaulin), inline(always))]
41 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
42 Ok(match value {
43 "abstract" | "ABSTRACT" | "Abstract" => Restriction::Abstract,
44 "blacklist" | "BLACKLIST" | "BlackList" | "blackList" | "Blacklist" => Restriction::Blacklist,
45 _ => return Err(UnknownRestriction(value)),
46 })
47 }
48}
49
50#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
52#[cfg_attr(feature = "serde", derive(serde::Serialize))]
53#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
54#[non_exhaustive]
55pub enum Restriction {
56 Abstract,
58 Blacklist,
60}
61
62impl core::fmt::Display for Restriction {
63 #[cfg_attr(not(tarpaulin), inline(always))]
64 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65 write!(f, "{}", self.as_str())
66 }
67}
68
69impl Restriction {
70 #[cfg_attr(not(tarpaulin), inline(always))]
72 pub const fn as_str(&self) -> &'static str {
73 match self {
74 Self::Abstract => "abstract",
75 Self::Blacklist => "blacklist",
76 }
77 }
78
79 #[cfg_attr(not(tarpaulin), inline(always))]
81 pub const fn is_abstract(&self) -> bool {
82 matches!(self, Self::Abstract)
83 }
84
85 #[cfg_attr(not(tarpaulin), inline(always))]
87 pub const fn is_blacklist(&self) -> bool {
88 matches!(self, Self::Blacklist)
89 }
90}
91
92#[cfg(any(feature = "ontology", feature = "rated"))]
97macro_rules! define_sound_event {
98 (
99 $(#[$struct_meta:meta])*
100 name: $name:ident,
101 $(#[$err_meta:meta])*
102 error: $err_name:ident,
103 error_message: $err_msg:literal
104 $(,
105 extra_fields: {
106 $($extra_field:tt)*
107 }
108 )?
109 $(,
110 extra_impl: {
111 $($extra_impl:tt)*
112 }
113 )?
114 $(,)?
115 ) => {
116 $(#[$struct_meta])*
117 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
118 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
119 pub struct $name {
120 #[cfg_attr(feature = "serde", serde(skip))]
121 pub(crate) code: u64,
122 pub(crate) id: &'static str,
123 pub(crate) name: &'static str,
124 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "<[_]>::is_empty"))]
125 pub(crate) aliases: &'static [&'static str],
126 pub(crate) description: &'static str,
127 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
128 pub(crate) citation_uri: ::core::option::Option<&'static str>,
129 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "<[_]>::is_empty"))]
130 pub(crate) children: &'static [&'static $name],
131 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "<[_]>::is_empty"))]
132 pub(crate) restrictions: &'static [$crate::Restriction],
133 $($($extra_field)*)?
134 }
135
136 impl ::core::fmt::Display for $name {
137 #[cfg_attr(not(tarpaulin), inline(always))]
138 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
139 f.write_str(self.name)
140 }
141 }
142
143 impl $name {
144 #[cfg_attr(not(tarpaulin), inline(always))]
146 pub const fn encode(&self) -> u64 {
147 self.code
148 }
149
150 #[cfg_attr(not(tarpaulin), inline(always))]
152 pub const fn id(&self) -> &'static str {
153 self.id
154 }
155
156 #[cfg_attr(not(tarpaulin), inline(always))]
158 pub const fn name(&self) -> &'static str {
159 self.name
160 }
161
162 #[cfg_attr(not(tarpaulin), inline(always))]
164 pub const fn description(&self) -> &'static str {
165 self.description
166 }
167
168 #[cfg_attr(not(tarpaulin), inline(always))]
170 pub const fn aliases(&self) -> &'static [&'static str] {
171 self.aliases
172 }
173
174 #[cfg_attr(not(tarpaulin), inline(always))]
176 pub const fn citation_uri(&self) -> ::core::option::Option<&'static str> {
177 self.citation_uri
178 }
179
180 #[cfg_attr(not(tarpaulin), inline(always))]
182 pub const fn children(&self) -> &'static [&'static Self] {
183 self.children
184 }
185
186 #[cfg_attr(not(tarpaulin), inline(always))]
188 pub const fn restrictions(&self) -> &'static [$crate::Restriction] {
189 self.restrictions
190 }
191
192 $($($extra_impl)*)?
193 }
194
195 $(#[$err_meta])*
196 #[derive(Debug, ::thiserror::Error, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
197 #[error($err_msg)]
198 pub struct $err_name(pub(crate) u64);
199
200 impl $err_name {
201 #[cfg_attr(not(tarpaulin), inline(always))]
203 pub const fn code(&self) -> u64 {
204 self.0
205 }
206 }
207 };
208}
209
210#[cfg(any(feature = "ontology", feature = "rated"))]
211pub(crate) use define_sound_event;