asset handles now use uuids instead of ascending ints

This commit is contained in:
Carter Anderson 2020-05-02 18:35:18 -07:00
parent 71a4503df1
commit 24e5238e75
4 changed files with 137 additions and 124 deletions

View file

@ -6,3 +6,5 @@ edition = "2018"
[dependencies] [dependencies]
bevy_core = { path = "../bevy_core" } bevy_core = { path = "../bevy_core" }
uuid = { version = "0.8", features = ["v4"] }

View file

@ -0,0 +1,118 @@
use std::{
fmt::Debug,
hash::{Hash, Hasher},
};
use std::{any::TypeId, marker::PhantomData};
use uuid::Uuid;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct HandleId(Uuid);
pub const DEFAULT_HANDLE_ID: HandleId = HandleId(Uuid::from_bytes([
238, 232, 56, 216, 245, 246, 77, 29, 165, 188, 211, 202, 249, 248, 15, 4,
]));
impl HandleId {
pub fn new() -> HandleId {
HandleId(Uuid::new_v4())
}
}
pub struct Handle<T> {
pub id: HandleId,
marker: PhantomData<T>,
}
impl<T> Handle<T> {
pub fn new(id: HandleId) -> Self {
Handle {
id,
marker: PhantomData,
}
}
pub fn from_untyped(untyped_handle: HandleUntyped) -> Option<Handle<T>>
where
T: 'static,
{
if TypeId::of::<T>() == untyped_handle.type_id {
Some(Handle::new(untyped_handle.id))
} else {
None
}
}
}
impl<T> Hash for Handle<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
impl<T> PartialEq for Handle<T> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl<T> Eq for Handle<T> {}
impl<T> Debug for Handle<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
let name = std::any::type_name::<T>().split("::").last().unwrap();
write!(f, "Handle<{}>({:?})", name, self.id.0)
}
}
impl<T> Default for Handle<T> {
fn default() -> Self {
Handle {
id: DEFAULT_HANDLE_ID,
marker: PhantomData,
}
}
}
impl<T> Clone for Handle<T> {
fn clone(&self) -> Self {
Handle {
id: self.id.clone(),
marker: PhantomData,
}
}
}
impl<T> Copy for Handle<T> {}
#[derive(Hash, Copy, Clone, Eq, PartialEq, Debug)]
pub struct HandleUntyped {
pub id: HandleId,
pub type_id: TypeId,
}
impl HandleUntyped {
pub fn is_handle<T: 'static>(untyped: &HandleUntyped) -> bool {
TypeId::of::<T>() == untyped.type_id
}
}
impl<T> From<Handle<T>> for HandleUntyped
where
T: 'static,
{
fn from(handle: Handle<T>) -> Self {
HandleUntyped {
id: handle.id,
type_id: TypeId::of::<T>(),
}
}
}
impl<T> From<HandleUntyped> for Handle<T>
where
T: 'static,
{
fn from(handle: HandleUntyped) -> Self {
Handle::from_untyped(handle)
.expect("attempted to convert untyped handle to incorrect typed handle")
}
}

View file

@ -1,113 +1,8 @@
mod handle;
pub use handle::*;
use bevy_core::bytes::GetBytes; use bevy_core::bytes::GetBytes;
use std::{ use std::collections::HashMap;
fmt::Debug,
hash::{Hash, Hasher},
};
use std::{any::TypeId, collections::HashMap, marker::PhantomData};
// TODO: move these types to their own files
pub type HandleId = usize;
pub const DEFAULT_HANDLE_ID: HandleId = 0;
pub struct Handle<T> {
pub id: HandleId,
marker: PhantomData<T>,
}
impl<T> Handle<T> {
pub fn new(id: HandleId) -> Self {
Handle {
id,
marker: PhantomData,
}
}
pub fn from_untyped(untyped_handle: HandleUntyped) -> Option<Handle<T>>
where
T: 'static,
{
if TypeId::of::<T>() == untyped_handle.type_id {
Some(Handle::new(untyped_handle.id))
} else {
None
}
}
}
impl<T> Hash for Handle<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
impl<T> PartialEq for Handle<T> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl<T> Eq for Handle<T> {}
impl<T> Debug for Handle<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
let name = std::any::type_name::<T>().split("::").last().unwrap();
write!(f, "Handle<{}>({})", name, self.id)
}
}
impl<T> Default for Handle<T> {
fn default() -> Self {
Handle {
id: DEFAULT_HANDLE_ID,
marker: PhantomData,
}
}
}
impl<T> Copy for Handle<T> {}
impl<T> Clone for Handle<T> {
fn clone(&self) -> Self {
Handle {
id: self.id.clone(),
marker: PhantomData,
}
}
}
#[derive(Hash, Copy, Clone, Eq, PartialEq, Debug)]
pub struct HandleUntyped {
pub id: HandleId,
pub type_id: TypeId,
}
impl HandleUntyped {
pub fn is_handle<T: 'static>(untyped: &HandleUntyped) -> bool {
TypeId::of::<T>() == untyped.type_id
}
}
impl<T> From<Handle<T>> for HandleUntyped
where
T: 'static,
{
fn from(handle: Handle<T>) -> Self {
HandleUntyped {
id: handle.id,
type_id: TypeId::of::<T>(),
}
}
}
impl<T> From<HandleUntyped> for Handle<T>
where
T: 'static,
{
fn from(handle: HandleUntyped) -> Self {
Handle::from_untyped(handle)
.expect("attempted to convert untyped handle to incorrect typed handle")
}
}
pub trait Asset<D> { pub trait Asset<D> {
fn load(descriptor: D) -> Self; fn load(descriptor: D) -> Self;
@ -116,7 +11,6 @@ pub trait Asset<D> {
pub struct AssetStorage<T> { pub struct AssetStorage<T> {
assets: HashMap<HandleId, T>, assets: HashMap<HandleId, T>,
names: HashMap<String, Handle<T>>, names: HashMap<String, Handle<T>>,
current_index: HandleId,
} }
impl<T> AssetStorage<T> { impl<T> AssetStorage<T> {
@ -124,7 +18,6 @@ impl<T> AssetStorage<T> {
AssetStorage { AssetStorage {
assets: HashMap::new(), assets: HashMap::new(),
names: HashMap::new(), names: HashMap::new(),
current_index: DEFAULT_HANDLE_ID + 1, // ensure we don't start on the default handle id
} }
} }
@ -133,13 +26,13 @@ impl<T> AssetStorage<T> {
} }
pub fn add(&mut self, asset: T) -> Handle<T> { pub fn add(&mut self, asset: T) -> Handle<T> {
let id = self.current_index; let id = HandleId::new();
self.current_index += 1;
self.assets.insert(id, asset); self.assets.insert(id, asset);
Handle { Handle::new(id)
id,
marker: PhantomData,
} }
pub fn add_with_handle(&mut self, handle: Handle<T>, asset: T) {
self.assets.insert(handle.id, asset);
} }
pub fn add_default(&mut self, asset: T) -> Handle<T> { pub fn add_default(&mut self, asset: T) -> Handle<T> {

View file

@ -154,7 +154,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{Batch, BatchKey, Batcher}; use super::{Batch, BatchKey, Batcher};
use bevy_asset::{Handle, HandleUntyped}; use bevy_asset::{Handle, HandleUntyped, HandleId};
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
struct A; struct A;
@ -177,12 +177,12 @@ mod tests {
let e2 = Entity(2); let e2 = Entity(2);
let e3 = Entity(3); let e3 = Entity(3);
let a1: HandleUntyped = Handle::<A>::new(1).into(); let a1: HandleUntyped = Handle::<A>::new(HandleId::new()).into();
let b1: HandleUntyped = Handle::<B>::new(1).into(); let b1: HandleUntyped = Handle::<B>::new(HandleId::new()).into();
let c1: HandleUntyped = Handle::<C>::new(1).into(); let c1: HandleUntyped = Handle::<C>::new(HandleId::new()).into();
let a2: HandleUntyped = Handle::<A>::new(2).into(); let a2: HandleUntyped = Handle::<A>::new(HandleId::new()).into();
let b2: HandleUntyped = Handle::<B>::new(2).into(); let b2: HandleUntyped = Handle::<B>::new(HandleId::new()).into();
let a1_b1 = BatchKey::key2(a1, b1); let a1_b1 = BatchKey::key2(a1, b1);
let a2_b2 = BatchKey::key2(a2, b2); let a2_b2 = BatchKey::key2(a2, b2);