1use alloc::string::String;
4
5#[non_exhaustive]
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub enum QueryError {
9 UnregisteredComponent { name: String },
11 WrongStorageKind { name: String },
13 ConflictingFilters { detail: String },
15 DuplicateMutableComponent { name: String },
17 WrongOwner,
19 StaleCache,
21 WrongQuery { detail: String },
23 MovingChangeWindow,
25 UnsupportedCachePolicy { detail: String },
27 ExactIdOrderConflict,
29 DuplicateExactId { entity: crate::EntityId },
31 MissingExactId { entity: crate::EntityId },
33 BorrowConflict { detail: String },
35 CommandRejected { detail: String },
37 OwnerMismatch,
39 TraversalAborted {
41 entity: crate::EntityId,
42 detail: String,
43 },
44}
45
46#[cfg(feature = "std")]
47impl core::fmt::Display for QueryError {
48 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
49 match self {
50 Self::UnregisteredComponent { name } => write!(f, "unregistered component '{name}'"),
51 Self::WrongStorageKind { name } => write!(f, "wrong storage kind for '{name}'"),
52 Self::ConflictingFilters { detail } => write!(f, "conflicting filters: {detail}"),
53 Self::DuplicateMutableComponent { name } => {
54 write!(f, "duplicate mutable component '{name}'")
55 }
56 Self::WrongOwner => f.write_str("query handle belongs to another world"),
57 Self::StaleCache => f.write_str("stale query cache handle"),
58 Self::WrongQuery { detail } => write!(f, "wrong query cursor: {detail}"),
59 Self::MovingChangeWindow => f.write_str(
60 "added/changed filters require a traversal or membership policy, not Result",
61 ),
62 Self::UnsupportedCachePolicy { detail } => {
63 write!(f, "unsupported cache policy: {detail}")
64 }
65 Self::ExactIdOrderConflict => f.write_str("exact-id order conflicts with result cache"),
66 Self::DuplicateExactId { entity } => {
67 write!(f, "exact-id query contains duplicate entity {entity:?}")
68 }
69 Self::MissingExactId { entity } => {
70 write!(f, "exact-id query missing unavailable entity {entity:?}")
71 }
72 Self::BorrowConflict { detail } => write!(f, "query borrow conflict: {detail}"),
73 Self::CommandRejected { detail } => write!(f, "query command rejected: {detail}"),
74 Self::OwnerMismatch => f.write_str("query handle owner mismatch"),
75 Self::TraversalAborted { entity, detail } => {
76 write!(f, "query traversal aborted at {entity:?}: {detail}")
77 }
78 }
79 }
80}
81
82#[cfg(feature = "std")]
83impl std::error::Error for QueryError {}
84
85#[cfg(all(test, feature = "std"))]
86mod tests {
87 use super::*;
88 use crate::component::ComponentOptions;
89 use crate::world::WorldBuilder;
90 use alloc::string::ToString;
91
92 #[test]
93 fn display_covers_entity_and_command_diagnostics() {
94 let mut builder = WorldBuilder::new();
95 builder
96 .register_component::<u8>(ComponentOptions::sparse())
97 .expect("component");
98 let mut world = builder.build().expect("world");
99 let entity = world.spawn().expect("entity");
100
101 assert!(QueryError::DuplicateExactId { entity }
102 .to_string()
103 .contains("duplicate entity"));
104 assert_eq!(
105 QueryError::CommandRejected {
106 detail: String::from("stale target"),
107 }
108 .to_string(),
109 "query command rejected: stale target"
110 );
111 }
112}