1use uuid::{Uuid, uuid};
4
5#[cfg(feature = "chumsky")]
6use chumsky::{
7 IterParser as _, Parser,
8 prelude::{just, one_of},
9};
10
11#[cfg(feature = "chumsky")]
17#[must_use]
18pub fn uuid_parser<'src>()
19-> impl Parser<'src, &'src str, uuid::Uuid, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
20 one_of("0123456789abcdef")
21 .repeated()
22 .exactly(8)
23 .collect::<String>()
24 .then_ignore(just('-'))
25 .then(
26 one_of("0123456789abcdef")
27 .repeated()
28 .exactly(4)
29 .collect::<String>(),
30 )
31 .then_ignore(just('-'))
32 .then(
33 one_of("0123456789abcdef")
34 .repeated()
35 .exactly(4)
36 .collect::<String>(),
37 )
38 .then_ignore(just('-'))
39 .then(
40 one_of("0123456789abcdef")
41 .repeated()
42 .exactly(4)
43 .collect::<String>(),
44 )
45 .then_ignore(just('-'))
46 .then(
47 one_of("0123456789abcdef")
48 .repeated()
49 .exactly(12)
50 .collect::<String>(),
51 )
52 .try_map(|((((a, b), c), d), e), span: chumsky::span::SimpleSpan| {
53 uuid::Uuid::parse_str(&format!("{a}-{b}-{c}-{d}-{e}"))
54 .map_err(|e| chumsky::error::Rich::custom(span, format!("{e:?}")))
55 })
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
61pub struct Key(pub Uuid);
62
63impl std::fmt::Display for Key {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(f, "{}", self.0)
66 }
67}
68
69#[cfg(feature = "chumsky")]
75#[must_use]
76#[expect(
77 clippy::module_name_repetitions,
78 reason = "the parser is going to be used outside this module"
79)]
80pub fn key_parser<'src>()
81-> impl Parser<'src, &'src str, Key, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
82 uuid_parser().map(Key)
83}
84
85pub const NULL_KEY: Key = Key(uuid!("00000000-0000-0000-0000-000000000000"));
88
89pub const COMBAT_LOG_ID: Key = Key(uuid!("45e0fcfa-2268-4490-a51c-3e51bdfe80d1"));
91
92#[derive(Debug, Clone, PartialEq, Eq)]
94#[expect(
95 clippy::module_name_repetitions,
96 reason = "the type is going to be used outside this module"
97)]
98pub struct AgentKey(pub Key);
99
100impl std::fmt::Display for AgentKey {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 write!(f, "{}", self.0)
103 }
104}
105
106impl From<AgentKey> for Key {
107 fn from(val: AgentKey) -> Self {
108 val.0
109 }
110}
111
112#[cfg(feature = "chumsky")]
118#[must_use]
119pub fn agent_key_parser<'src>()
120-> impl Parser<'src, &'src str, AgentKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
121 key_parser().map(AgentKey)
122}
123
124#[cfg(feature = "chumsky")]
131#[must_use]
132pub fn app_agent_uri_as_agent_key_parser<'src>()
133-> impl Parser<'src, &'src str, AgentKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
134 crate::viewer_uri::viewer_app_agent_uri_parser().try_map(|uri, span| match uri {
135 crate::viewer_uri::ViewerUri::AgentAbout(agent_key)
136 | crate::viewer_uri::ViewerUri::AgentInspect(agent_key) => Ok(agent_key),
137 _ => Err(chumsky::error::Rich::custom(
138 span,
139 "Unexpected type of Agent viewer URI",
140 )),
141 })
142}
143
144#[derive(Debug, Clone, PartialEq, Eq)]
146#[expect(
147 clippy::module_name_repetitions,
148 reason = "the type is going to be used outside this module"
149)]
150pub struct ClassifiedKey(pub Key);
151
152impl std::fmt::Display for ClassifiedKey {
153 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154 write!(f, "{}", self.0)
155 }
156}
157
158impl From<ClassifiedKey> for Key {
159 fn from(val: ClassifiedKey) -> Self {
160 val.0
161 }
162}
163
164#[cfg(feature = "chumsky")]
170#[must_use]
171pub fn classified_key_parser<'src>()
172-> impl Parser<'src, &'src str, ClassifiedKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
173{
174 key_parser().map(ClassifiedKey)
175}
176
177#[derive(Debug, Clone, PartialEq, Eq)]
179#[expect(
180 clippy::module_name_repetitions,
181 reason = "the type is going to be used outside this module"
182)]
183pub struct EventKey(pub Key);
184
185impl std::fmt::Display for EventKey {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 write!(f, "{}", self.0)
188 }
189}
190
191impl From<EventKey> for Key {
192 fn from(val: EventKey) -> Self {
193 val.0
194 }
195}
196
197#[cfg(feature = "chumsky")]
203#[must_use]
204pub fn event_key_parser<'src>()
205-> impl Parser<'src, &'src str, EventKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
206 key_parser().map(EventKey)
207}
208
209#[derive(Debug, Clone, PartialEq, Eq)]
211#[expect(
212 clippy::module_name_repetitions,
213 reason = "the type is going to be used outside this module"
214)]
215pub struct ExperienceKey(pub Key);
216
217impl std::fmt::Display for ExperienceKey {
218 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
219 write!(f, "{}", self.0)
220 }
221}
222
223impl From<ExperienceKey> for Key {
224 fn from(val: ExperienceKey) -> Self {
225 val.0
226 }
227}
228
229#[cfg(feature = "chumsky")]
235#[must_use]
236pub fn experience_key_parser<'src>()
237-> impl Parser<'src, &'src str, ExperienceKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
238{
239 key_parser().map(ExperienceKey)
240}
241
242#[derive(Debug, Clone, PartialEq, Eq)]
244#[expect(
245 clippy::module_name_repetitions,
246 reason = "the type is going to be used outside this module"
247)]
248pub struct FriendKey(pub Key);
249
250impl std::fmt::Display for FriendKey {
251 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252 write!(f, "{}", self.0)
253 }
254}
255
256impl From<FriendKey> for Key {
257 fn from(val: FriendKey) -> Self {
258 val.0
259 }
260}
261
262impl From<FriendKey> for AgentKey {
263 fn from(val: FriendKey) -> Self {
264 Self(val.0)
265 }
266}
267
268#[cfg(feature = "chumsky")]
274#[must_use]
275pub fn friend_key_parser<'src>()
276-> impl Parser<'src, &'src str, FriendKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
277 key_parser().map(FriendKey)
278}
279
280#[derive(Debug, Clone, PartialEq, Eq)]
282#[expect(
283 clippy::module_name_repetitions,
284 reason = "the type is going to be used outside this module"
285)]
286pub struct GroupKey(pub Key);
287
288impl std::fmt::Display for GroupKey {
289 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
290 write!(f, "{}", self.0)
291 }
292}
293
294impl From<GroupKey> for Key {
295 fn from(val: GroupKey) -> Self {
296 val.0
297 }
298}
299
300#[cfg(feature = "chumsky")]
306#[must_use]
307pub fn group_key_parser<'src>()
308-> impl Parser<'src, &'src str, GroupKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
309 key_parser().map(GroupKey)
310}
311
312#[cfg(feature = "chumsky")]
319#[must_use]
320pub fn app_group_uri_as_group_key_parser<'src>()
321-> impl Parser<'src, &'src str, GroupKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
322 crate::viewer_uri::viewer_app_group_uri_parser().try_map(|uri, span| match uri {
323 crate::viewer_uri::ViewerUri::GroupAbout(group_key)
324 | crate::viewer_uri::ViewerUri::GroupInspect(group_key) => Ok(group_key),
325 _ => Err(chumsky::error::Rich::custom(
326 span,
327 "Unexpected type of group viewer URI",
328 )),
329 })
330}
331
332#[derive(Debug, Clone, PartialEq, Eq)]
334#[expect(
335 clippy::module_name_repetitions,
336 reason = "the type is going to be used outside this module"
337)]
338pub struct InventoryKey(pub Key);
339
340impl std::fmt::Display for InventoryKey {
341 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
342 write!(f, "{}", self.0)
343 }
344}
345
346impl From<InventoryKey> for Key {
347 fn from(val: InventoryKey) -> Self {
348 val.0
349 }
350}
351
352#[cfg(feature = "chumsky")]
358#[must_use]
359pub fn inventory_key_parser<'src>()
360-> impl Parser<'src, &'src str, InventoryKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
361{
362 key_parser().map(InventoryKey)
363}
364
365#[derive(Debug, Clone, PartialEq, Eq)]
367#[expect(
368 clippy::module_name_repetitions,
369 reason = "the type is going to be used outside this module"
370)]
371pub struct ObjectKey(pub Key);
372
373impl std::fmt::Display for ObjectKey {
374 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
375 write!(f, "{}", self.0)
376 }
377}
378
379impl From<ObjectKey> for Key {
380 fn from(val: ObjectKey) -> Self {
381 val.0
382 }
383}
384
385#[cfg(feature = "chumsky")]
391#[must_use]
392pub fn object_key_parser<'src>()
393-> impl Parser<'src, &'src str, ObjectKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
394 key_parser().map(ObjectKey)
395}
396
397#[derive(Debug, Clone, PartialEq, Eq)]
399#[expect(
400 clippy::module_name_repetitions,
401 reason = "the type is going to be used outside this module"
402)]
403pub struct ParcelKey(pub Key);
404
405impl std::fmt::Display for ParcelKey {
406 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
407 write!(f, "{}", self.0)
408 }
409}
410
411impl From<ParcelKey> for Key {
412 fn from(val: ParcelKey) -> Self {
413 val.0
414 }
415}
416
417#[cfg(feature = "chumsky")]
423#[must_use]
424pub fn parcel_key_parser<'src>()
425-> impl Parser<'src, &'src str, ParcelKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
426 key_parser().map(ParcelKey)
427}
428
429#[derive(Debug, Clone, PartialEq, Eq)]
431#[expect(
432 clippy::module_name_repetitions,
433 reason = "the type is going to be used outside this module"
434)]
435pub struct TextureKey(pub Key);
436
437impl std::fmt::Display for TextureKey {
438 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
439 write!(f, "{}", self.0)
440 }
441}
442
443impl From<TextureKey> for Key {
444 fn from(val: TextureKey) -> Self {
445 val.0
446 }
447}
448
449#[cfg(feature = "chumsky")]
455#[must_use]
456pub fn texture_key_parser<'src>()
457-> impl Parser<'src, &'src str, TextureKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
458 key_parser().map(TextureKey)
459}
460
461#[derive(Debug, Clone, PartialEq, Eq)]
463#[expect(
464 clippy::module_name_repetitions,
465 reason = "the type is going to be used outside this module"
466)]
467pub struct InventoryFolderKey(pub Key);
468
469impl std::fmt::Display for InventoryFolderKey {
470 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
471 write!(f, "{}", self.0)
472 }
473}
474
475impl From<InventoryFolderKey> for Key {
476 fn from(val: InventoryFolderKey) -> Self {
477 val.0
478 }
479}
480
481#[cfg(feature = "chumsky")]
487#[must_use]
488pub fn inventory_folder_key_parser<'src>() -> impl Parser<
489 'src,
490 &'src str,
491 InventoryFolderKey,
492 chumsky::extra::Err<chumsky::error::Rich<'src, char>>,
493> {
494 key_parser().map(InventoryFolderKey)
495}
496
497#[derive(Debug, Clone, PartialEq, Eq, strum::EnumIs)]
499#[expect(
500 clippy::module_name_repetitions,
501 reason = "the type is going to be used outside this module"
502)]
503pub enum OwnerKey {
504 Agent(AgentKey),
506 Group(GroupKey),
508}
509
510impl std::fmt::Display for OwnerKey {
511 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
512 match self {
513 Self::Agent(agent_key) => write!(f, "{agent_key}"),
514 Self::Group(group_key) => write!(f, "{group_key}"),
515 }
516 }
517}
518
519#[derive(Debug, Clone)]
521pub struct OwnerIsGroupError(GroupKey);
522
523impl std::fmt::Display for OwnerIsGroupError {
524 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
525 write!(f, "The owner is not an agent but the group {}", self.0)
526 }
527}
528
529impl TryInto<AgentKey> for OwnerKey {
530 type Error = OwnerIsGroupError;
531
532 fn try_into(self) -> Result<AgentKey, Self::Error> {
533 match self {
534 Self::Agent(agent_key) => Ok(agent_key),
535 Self::Group(group_key) => Err(OwnerIsGroupError(group_key)),
536 }
537 }
538}
539
540#[derive(Debug, Clone)]
542pub struct OwnerIsAgentError(AgentKey);
543
544impl std::fmt::Display for OwnerIsAgentError {
545 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
546 write!(f, "The owner is not a group but the agent {}", self.0)
547 }
548}
549
550impl TryInto<GroupKey> for OwnerKey {
551 type Error = OwnerIsAgentError;
552
553 fn try_into(self) -> Result<GroupKey, Self::Error> {
554 match self {
555 Self::Agent(agent_key) => Err(OwnerIsAgentError(agent_key)),
556 Self::Group(group_key) => Ok(group_key),
557 }
558 }
559}
560
561impl From<OwnerKey> for Key {
562 fn from(val: OwnerKey) -> Self {
563 match val {
564 OwnerKey::Agent(agent_key) => agent_key.into(),
565 OwnerKey::Group(group_key) => group_key.into(),
566 }
567 }
568}
569
570#[cfg(feature = "chumsky")]
577#[must_use]
578pub fn app_agent_or_group_uri_as_owner_key_parser<'src>()
579-> impl Parser<'src, &'src str, OwnerKey, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
580 app_agent_uri_as_agent_key_parser()
581 .map(OwnerKey::Agent)
582 .or(app_group_uri_as_group_key_parser().map(OwnerKey::Group))
583}