Skip to content

Commit 49b2ebe

Browse files
authored
Merge pull request #8 from mintlu8/rc
0.16
2 parents 168a34b + 063cc77 commit 49b2ebe

File tree

20 files changed

+1043
-453
lines changed

20 files changed

+1043
-453
lines changed

Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ rustdoc-args = ["--cfg", "docsrs"]
3434
bevy_serde_lens_core = { version = "0.16.0", path = "./core" }
3535
bevy_serde_lens_derive = { version = "0.1", path = "./derive", optional = true }
3636

37-
bevy_ecs = "0.16.0-rc.3"
38-
bevy_app = "0.16.0-rc.3"
39-
bevy_asset = "0.16.0-rc.3"
40-
bevy_reflect = "0.16.0-rc.3"
37+
bevy_ecs = "0.16.0"
38+
bevy_app = "0.16.0"
39+
bevy_asset = "0.16.0"
40+
bevy_reflect = "0.16.0"
41+
bevy_state = "0.16.0"
4142

4243
erased-serde = "0.4.3"
4344
itertools = "0.13.0"
@@ -49,7 +50,7 @@ scoped-tls-hkt = "0.1.4"
4950
linkme = { version = "0.3.31", optional = true }
5051

5152
[dev-dependencies]
52-
bevy_scene = "0.16.0-rc.3"
53+
bevy_scene = "0.16.0"
5354
criterion = "0.5.1"
5455
postcard = { version = "1.0.8", default-features = false, features = ["alloc"] }
5556
rand = "0.8.5"

core/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ World access module for bevy_serde_lens.
1515
keywords = ["bevy", "serde", "serialize", "save"]
1616

1717
[dependencies]
18-
bevy_ecs = "0.16.0-rc.3"
18+
bevy_ecs = "0.16.0"
1919
scoped-tls-hkt = "0.1.4"
20+
serde = { version = "1.0.219", default-features = false }

core/src/de.rs

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
use crate::{ENTITY, WORLD_MUT};
2+
use bevy_ecs::bundle::Bundle;
3+
use bevy_ecs::component::{Component, Mutable};
4+
use bevy_ecs::entity::Entity;
5+
use bevy_ecs::query::ReadOnlyQueryData;
6+
use bevy_ecs::resource::Resource;
7+
use bevy_ecs::world::{EntityWorldMut, Mut, World};
8+
use serde::de::Error as DError;
9+
use serde::Deserializer;
10+
use std::convert::Infallible;
11+
use std::fmt::Display;
12+
13+
/// Useful commands for deserialization.
14+
pub struct DeUtils(Infallible);
15+
16+
macro_rules! validate_world {
17+
() => {
18+
if !WORLD_MUT.is_set() {
19+
return Err(DError::custom(
20+
"Cannot deserialize outside of a `deserialize` scope.",
21+
));
22+
}
23+
};
24+
}
25+
26+
impl DeUtils {
27+
/// Run a function on a mutable only reference to [`World`].
28+
///
29+
/// # Errors
30+
///
31+
/// * If used outside of a `Deserialize` implementation.
32+
/// * If used outside `bevy_serde_lens`.
33+
/// * If used in a nested manner, as that is a violation to rust's aliasing rule.
34+
///
35+
/// ```
36+
/// with_world_mut(|| {
37+
/// // panics here
38+
/// with_world_mut(|| {
39+
/// ..
40+
/// })
41+
/// })
42+
/// ```
43+
#[inline(always)]
44+
pub fn with_world_mut<'de, D: Deserializer<'de>, T>(
45+
f: impl FnOnce(&mut World) -> T,
46+
) -> Result<T, D::Error> {
47+
validate_world!();
48+
Ok(WORLD_MUT.with(f))
49+
}
50+
51+
#[doc(hidden)]
52+
pub fn with_world_mut_err<D: DError, T>(f: impl FnOnce(&mut World) -> T) -> Result<T, D> {
53+
validate_world!();
54+
Ok(WORLD_MUT.with(f))
55+
}
56+
57+
/// Obtain the current [`Entity`] in `bevy_serde_lens`.
58+
///
59+
/// # Errors
60+
///
61+
/// * If used outside `bevy_serde_lens`.
62+
#[inline(always)]
63+
pub fn current_entity<'de, D: Deserializer<'de>>() -> Result<Entity, D::Error> {
64+
ENTITY
65+
.get()
66+
.ok_or_else(|| DError::custom("No active entity in deserialization found."))
67+
}
68+
69+
pub fn with_entity_mut<'de, D: Deserializer<'de>, T>(
70+
f: impl FnOnce(EntityWorldMut) -> T,
71+
) -> Result<T, D::Error> {
72+
validate_world!();
73+
let Some(entity) = ENTITY.get() else {
74+
return Err(DError::custom("No active entity in serialization found."));
75+
};
76+
WORLD_MUT.with(|world| {
77+
world
78+
.get_entity_mut(entity)
79+
.map(f)
80+
.map_err(|_| DError::custom("Entity missing."))
81+
})
82+
}
83+
84+
#[doc(hidden)]
85+
pub fn with_entity_mut_err<D: DError, T>(f: impl FnOnce(EntityWorldMut) -> T) -> Result<T, D> {
86+
validate_world!();
87+
let Some(entity) = ENTITY.get() else {
88+
return Err(DError::custom("No active entity in serialization found."));
89+
};
90+
WORLD_MUT.with(|world| {
91+
world
92+
.get_entity_mut(entity)
93+
.map(f)
94+
.map_err(|_| DError::custom("Entity missing."))
95+
})
96+
}
97+
98+
pub fn with_query<'de, C: ReadOnlyQueryData, D: Deserializer<'de>, T>(
99+
f: impl FnOnce(C::Item<'_>) -> T,
100+
) -> Result<T, D::Error> {
101+
validate_world!();
102+
let Some(entity) = ENTITY.get() else {
103+
return Err(DError::custom("No active entity in serialization found."));
104+
};
105+
WORLD_MUT.with(|world| {
106+
world
107+
.get_entity(entity)
108+
.map_err(|_| DError::custom("Entity missing."))?
109+
.get_components::<C>()
110+
.map(f)
111+
.ok_or_else(|| DError::custom("One or more component missing."))
112+
})
113+
}
114+
115+
pub fn with_component<'de, C: Component, D: Deserializer<'de>, T>(
116+
f: impl FnOnce(&C) -> T,
117+
) -> Result<T, D::Error> {
118+
validate_world!();
119+
let Some(entity) = ENTITY.get() else {
120+
return Err(DError::custom("No active entity in serialization found."));
121+
};
122+
WORLD_MUT.with(|world| {
123+
world
124+
.get_entity(entity)
125+
.map_err(|_| DError::custom("Entity missing."))?
126+
.get::<C>()
127+
.map(f)
128+
.ok_or_else(|| DError::custom("Component missing."))
129+
})
130+
}
131+
132+
pub fn with_component_mut<'de, C: Component<Mutability = Mutable>, D: Deserializer<'de>, T>(
133+
f: impl FnOnce(Mut<C>) -> T,
134+
) -> Result<T, D::Error> {
135+
validate_world!();
136+
let Some(entity) = ENTITY.get() else {
137+
return Err(DError::custom("No active entity in serialization found."));
138+
};
139+
WORLD_MUT.with(|world| {
140+
world
141+
.get_entity_mut(entity)
142+
.map_err(|_| DError::custom("Entity missing."))?
143+
.get_mut::<C>()
144+
.map(f)
145+
.ok_or_else(|| DError::custom("Component missing."))
146+
})
147+
}
148+
149+
pub fn with_resource<'de, R: Resource, D: Deserializer<'de>, T>(
150+
f: impl FnOnce(&R) -> T,
151+
) -> Result<T, D::Error> {
152+
validate_world!();
153+
WORLD_MUT.with(|world| {
154+
world
155+
.get_resource::<R>()
156+
.map(f)
157+
.ok_or_else(|| DError::custom("Resource missing."))
158+
})
159+
}
160+
161+
pub fn with_resource_mut<'de, R: Resource, D: Deserializer<'de>, T>(
162+
f: impl FnOnce(Mut<R>) -> T,
163+
) -> Result<T, D::Error> {
164+
validate_world!();
165+
WORLD_MUT.with(|world| {
166+
world
167+
.get_resource_mut::<R>()
168+
.map(f)
169+
.ok_or_else(|| DError::custom("Resource missing."))
170+
})
171+
}
172+
173+
pub fn with_non_send_resource<'de, R: 'static, D: Deserializer<'de>, T>(
174+
f: impl FnOnce(&R) -> T,
175+
) -> Result<T, D::Error> {
176+
validate_world!();
177+
WORLD_MUT.with(|world| {
178+
world
179+
.get_non_send_resource::<R>()
180+
.map(f)
181+
.ok_or_else(|| DError::custom("Resource missing."))
182+
})
183+
}
184+
185+
pub fn with_non_send_resource_mut<'de, R: 'static, D: Deserializer<'de>, T>(
186+
f: impl FnOnce(Mut<R>) -> T,
187+
) -> Result<T, D::Error> {
188+
validate_world!();
189+
WORLD_MUT.with(|world| {
190+
world
191+
.get_non_send_resource_mut::<R>()
192+
.map(f)
193+
.ok_or_else(|| DError::custom("Resource missing."))
194+
})
195+
}
196+
197+
pub fn insert<'de, D: Deserializer<'de>>(bundle: impl Bundle) -> Result<(), D::Error> {
198+
let Some(entity) = ENTITY.get() else {
199+
return Err(DError::custom("No active entity in serialization found."));
200+
};
201+
if !WORLD_MUT.is_set() {
202+
return Err(DError::custom(
203+
"Cannot deserialize outside of a `deserialize` scope.",
204+
));
205+
}
206+
WORLD_MUT.with(|world| {
207+
world
208+
.get_entity_mut(entity)
209+
.map(|mut x| {
210+
x.insert(bundle);
211+
})
212+
.map_err(|_| DError::custom("Entity missing."))
213+
})
214+
}
215+
216+
pub fn error<'de, D: Deserializer<'de>>(string: impl Display) -> D::Error {
217+
DError::custom(string)
218+
}
219+
}

core/src/lib.rs

Lines changed: 9 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@
55
//! since this tracks `bevy` versions instead of
66
//! `bevy_serde_lens` versions.
77
8-
use std::{cell::Cell, fmt::Display};
8+
use std::cell::Cell;
99

1010
use bevy_ecs::{entity::Entity, world::World};
1111

12+
mod de;
13+
mod scope;
14+
mod ser;
15+
16+
pub use de::DeUtils;
17+
pub use scope::ScopeUtils;
18+
pub use ser::SerUtils;
19+
1220
scoped_tls_hkt::scoped_thread_local!(
1321
static WORLD: World
1422
);
@@ -20,106 +28,3 @@ scoped_tls_hkt::scoped_thread_local!(
2028
thread_local! {
2129
static ENTITY: Cell<Option<Entity>> = const {Cell::new(None)}
2230
}
23-
24-
/// Error of `bevy_serde_lens_core`.
25-
#[derive(Debug)]
26-
pub struct Error(&'static str);
27-
28-
impl Display for Error {
29-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30-
f.write_str(self.0)
31-
}
32-
}
33-
34-
impl std::error::Error for Error {}
35-
36-
/// Run a function on a read only reference to [`World`].
37-
///
38-
/// # Errors
39-
///
40-
/// * If used outside of a `Serialize` implementation.
41-
/// * If used outside `bevy_serde_lens`.
42-
#[inline(always)]
43-
pub fn with_world<T>(f: impl FnOnce(&World) -> T) -> Result<T, Error> {
44-
if !WORLD.is_set() {
45-
Err(Error("Cannot serialize outside a `serialize` scope."))
46-
} else {
47-
Ok(WORLD.with(f))
48-
}
49-
}
50-
51-
/// Run a function on a mutable only reference to [`World`].
52-
///
53-
/// # Errors
54-
///
55-
/// * If used outside of a `Deserialize` implementation.
56-
/// * If used outside `bevy_serde_lens`.
57-
/// * If used in a nested manner, as that is a violation to rust's aliasing rule.
58-
///
59-
/// ```
60-
/// with_world_mut(|| {
61-
/// // panics here
62-
/// with_world_mut(|| {
63-
/// ..
64-
/// })
65-
/// })
66-
/// ```
67-
#[inline(always)]
68-
pub fn with_world_mut<T>(f: impl FnOnce(&mut World) -> T) -> Result<T, Error> {
69-
if !WORLD_MUT.is_set() {
70-
Err(Error(
71-
"Cannot deserialize outside of a `deserialize` scope.",
72-
))
73-
} else {
74-
Ok(WORLD_MUT.with(f))
75-
}
76-
}
77-
78-
/// Obtain the current [`Entity`] in `bevy_serde_lens`.
79-
///
80-
/// # Errors
81-
///
82-
/// * If used outside `bevy_serde_lens`.
83-
#[inline(always)]
84-
pub fn current_entity() -> Result<Entity, Error> {
85-
ENTITY
86-
.get()
87-
.ok_or(Error("No active entity in serialization found."))
88-
}
89-
90-
/// Private module for `bevy_serde_lens`.
91-
///
92-
/// Only use these if you are doing custom serialization without `bevy_serde_lens`.
93-
/// For example when using some `bevy_serde_lens` only types with `DynamicScene`.
94-
pub mod private {
95-
use bevy_ecs::{entity::Entity, world::World};
96-
97-
use crate::{ENTITY, WORLD, WORLD_MUT};
98-
99-
/// Setup a `serialize` scope.
100-
#[inline(always)]
101-
pub fn ser_scope<T>(world: &World, f: impl FnOnce() -> T) -> T {
102-
WORLD.set(world, f)
103-
}
104-
105-
/// Setup a `deserialize` scope.
106-
#[inline(always)]
107-
pub fn de_scope<T>(world: &mut World, f: impl FnOnce() -> T) -> T {
108-
WORLD_MUT.set(world, f)
109-
}
110-
111-
struct DeferredEntity(Option<Entity>);
112-
113-
impl Drop for DeferredEntity {
114-
fn drop(&mut self) {
115-
ENTITY.set(self.0)
116-
}
117-
}
118-
119-
/// Setup an `Entity` scope.
120-
#[inline(always)]
121-
pub fn entity_scope<T>(entity: Entity, f: impl FnOnce() -> T) -> T {
122-
let _entity = DeferredEntity(ENTITY.replace(Some(entity)));
123-
f()
124-
}
125-
}

0 commit comments

Comments
 (0)