pub struct Access<T>where
T: SparseSetIndex,{ /* private fields */ }
Expand description
Tracks read and write access to specific elements in a collection.
Used internally to ensure soundness during system initialization and execution.
See the is_compatible
and get_conflicts
functions.
Implementations§
§impl<T> Access<T>where
T: SparseSetIndex,
impl<T> Access<T>where
T: SparseSetIndex,
pub fn add_read(&mut self, index: T)
pub fn add_read(&mut self, index: T)
Adds access to the element given by index
.
pub fn add_write(&mut self, index: T)
pub fn add_write(&mut self, index: T)
Adds exclusive access to the element given by index
.
pub fn add_archetypal(&mut self, index: T)
pub fn add_archetypal(&mut self, index: T)
Adds an archetypal (indirect) access to the element given by index
.
This is for elements whose values are not accessed (and thus will never cause conflicts), but whose presence in an archetype may affect query results.
Currently, this is only used for Has<T>
.
pub fn has_any_read(&self) -> bool
pub fn has_any_read(&self) -> bool
Returns true
if this can access anything.
pub fn has_write(&self, index: T) -> bool
pub fn has_write(&self, index: T) -> bool
Returns true
if this can exclusively access the element given by index
.
Examples found in repository?
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
fn main() {
let mut world = World::new();
let mut lines = std::io::stdin().lines();
let mut component_names = HashMap::<String, ComponentId>::new();
let mut component_info = HashMap::<ComponentId, ComponentInfo>::new();
println!("{}", PROMPT);
loop {
print!("\n> ");
let _ = std::io::stdout().flush();
let Some(Ok(line)) = lines.next() else {
return;
};
if line.is_empty() {
return;
};
let Some((first, rest)) = line.trim().split_once(|c: char| c.is_whitespace()) else {
match &line.chars().next() {
Some('c') => println!("{}", COMPONENT_PROMPT),
Some('s') => println!("{}", ENTITY_PROMPT),
Some('q') => println!("{}", QUERY_PROMPT),
_ => println!("{}", PROMPT),
}
continue;
};
match &first[0..1] {
"c" => {
rest.split(',').for_each(|component| {
let mut component = component.split_whitespace();
let Some(name) = component.next() else {
return;
};
let size = match component.next().map(|s| s.parse::<usize>()) {
Some(Ok(size)) => size,
_ => 0,
};
// Register our new component to the world with a layout specified by it's size
// SAFETY: [u64] is Send + Sync
let id = world.init_component_with_descriptor(unsafe {
ComponentDescriptor::new_with_layout(
name.to_string(),
StorageType::Table,
Layout::array::<u64>(size).unwrap(),
None,
)
});
let Some(info) = world.components().get_info(id) else {
return;
};
component_names.insert(name.to_string(), id);
component_info.insert(id, info.clone());
println!("Component {} created with id: {:?}", name, id.index());
});
}
"s" => {
let mut to_insert_ids = Vec::new();
let mut to_insert_data = Vec::new();
rest.split(',').for_each(|component| {
let mut component = component.split_whitespace();
let Some(name) = component.next() else {
return;
};
// Get the id for the component with the given name
let Some(&id) = component_names.get(name) else {
println!("Component {} does not exist", name);
return;
};
// Calculate the length for the array based on the layout created for this component id
let info = world.components().get_info(id).unwrap();
let len = info.layout().size() / std::mem::size_of::<u64>();
let mut values: Vec<u64> = component
.take(len)
.filter_map(|value| value.parse::<u64>().ok())
.collect();
values.resize(len, 0);
// Collect the id and array to be inserted onto our entity
to_insert_ids.push(id);
to_insert_data.push(values);
});
let mut entity = world.spawn_empty();
// Construct an `OwningPtr` for each component in `to_insert_data`
let to_insert_ptr = to_owning_ptrs(&mut to_insert_data);
// SAFETY:
// - Component ids have been taken from the same world
// - Each array is created to the layout specified in the world
unsafe {
entity.insert_by_ids(&to_insert_ids, to_insert_ptr.into_iter());
}
println!("Entity spawned with id: {:?}", entity.id());
}
"q" => {
let mut builder = QueryBuilder::<FilteredEntityMut>::new(&mut world);
parse_query(rest, &mut builder, &component_names);
let mut query = builder.build();
query.iter_mut(&mut world).for_each(|filtered_entity| {
let terms = filtered_entity
.components()
.map(|id| {
let ptr = filtered_entity.get_by_id(id).unwrap();
let info = component_info.get(&id).unwrap();
let len = info.layout().size() / std::mem::size_of::<u64>();
// SAFETY:
// - All components are created with layout [u64]
// - len is calculated from the component descriptor
let data = unsafe {
std::slice::from_raw_parts_mut(
ptr.assert_unique().as_ptr().cast::<u64>(),
len,
)
};
// If we have write access, increment each value once
if filtered_entity.access().has_write(id) {
data.iter_mut().for_each(|data| {
*data += 1;
});
}
format!("{}: {:?}", info.name(), data[0..len].to_vec())
})
.collect::<Vec<_>>()
.join(", ");
println!("{:?}: {}", filtered_entity.id(), terms);
});
}
_ => continue,
}
}
}
pub fn has_any_write(&self) -> bool
pub fn has_any_write(&self) -> bool
Returns true
if this accesses anything mutably.
pub fn has_archetypal(&self, index: T) -> bool
pub fn has_archetypal(&self, index: T) -> bool
Returns true if this has an archetypal (indirect) access to the element given by index
.
This is an element whose value is not accessed (and thus will never cause conflicts), but whose presence in an archetype may affect query results.
Currently, this is only used for Has<T>
.
pub fn read_all(&mut self)
pub fn read_all(&mut self)
Sets this as having access to all indexed elements (i.e. &World
).
pub fn write_all(&mut self)
pub fn write_all(&mut self)
Sets this as having mutable access to all indexed elements (i.e. EntityMut
).
pub fn has_read_all(&self) -> bool
pub fn has_read_all(&self) -> bool
Returns true
if this has access to all indexed elements (i.e. &World
).
pub fn has_write_all(&self) -> bool
pub fn has_write_all(&self) -> bool
Returns true
if this has write access to all indexed elements (i.e. EntityMut
).
pub fn clear_writes(&mut self)
pub fn clear_writes(&mut self)
Removes all writes.
pub fn clear(&mut self)
pub fn clear(&mut self)
Removes all accesses.
pub fn is_compatible(&self, other: &Access<T>) -> bool
pub fn is_compatible(&self, other: &Access<T>) -> bool
Returns true
if the access and other
can be active at the same time.
Access
instances are incompatible if one can write
an element that the other can read or write.
pub fn is_subset(&self, other: &Access<T>) -> bool
pub fn is_subset(&self, other: &Access<T>) -> bool
Returns true
if the set is a subset of another, i.e. other
contains
at least all the values in self
.
pub fn get_conflicts(&self, other: &Access<T>) -> Vec<T>
pub fn get_conflicts(&self, other: &Access<T>) -> Vec<T>
Returns a vector of elements that the access and other
cannot access at the same time.
pub fn reads_and_writes(&self) -> impl Iterator<Item = T>
pub fn reads_and_writes(&self) -> impl Iterator<Item = T>
Returns the indices of the elements this has access to.
pub fn reads(&self) -> impl Iterator<Item = T>
pub fn reads(&self) -> impl Iterator<Item = T>
Returns the indices of the elements this has non-exclusive access to.
pub fn writes(&self) -> impl Iterator<Item = T>
pub fn writes(&self) -> impl Iterator<Item = T>
Returns the indices of the elements this has exclusive access to.
pub fn archetypal(&self) -> impl Iterator<Item = T>
pub fn archetypal(&self) -> impl Iterator<Item = T>
Returns the indices of the elements that this has an archetypal access to.
These are elements whose values are not accessed (and thus will never cause conflicts), but whose presence in an archetype may affect query results.
Currently, this is only used for Has<T>
.
Trait Implementations§
§impl<T> Clone for Access<T>where
T: Clone + SparseSetIndex,
impl<T> Clone for Access<T>where
T: Clone + SparseSetIndex,
§impl<T> Debug for Access<T>where
T: SparseSetIndex + Debug,
impl<T> Debug for Access<T>where
T: SparseSetIndex + Debug,
§impl<T> Default for Access<T>where
T: SparseSetIndex,
impl<T> Default for Access<T>where
T: SparseSetIndex,
§impl<T> PartialEq for Access<T>where
T: PartialEq + SparseSetIndex,
impl<T> PartialEq for Access<T>where
T: PartialEq + SparseSetIndex,
impl<T> Eq for Access<T>where
T: Eq + SparseSetIndex,
impl<T> StructuralPartialEq for Access<T>where
T: SparseSetIndex,
Auto Trait Implementations§
impl<T> Freeze for Access<T>
impl<T> RefUnwindSafe for Access<T>where
T: RefUnwindSafe,
impl<T> Send for Access<T>where
T: Send,
impl<T> Sync for Access<T>where
T: Sync,
impl<T> Unpin for Access<T>where
T: Unpin,
impl<T> UnwindSafe for Access<T>where
T: UnwindSafe,
Blanket Implementations§
§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Self
using data from the given World
.§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
§impl<T> NoneValue for Twhere
T: Default,
impl<T> NoneValue for Twhere
T: Default,
type NoneType = T
§fn null_value() -> T
fn null_value() -> T
§impl<T> Pointable for T
impl<T> Pointable for T
source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian()
.