pub struct Ptr<'a, A = Aligned>(/* private fields */)
where
A: IsAligned;
Expand description
Type-erased borrow of some unknown type chosen when constructing this type.
This type tries to act “borrow-like” which means that:
- It should be considered immutable: its target must not be changed while this pointer is alive.
- It must always points to a valid value of whatever the pointee type is.
- The lifetime
'a
accurately represents how long the pointer is valid for. - Must be sufficiently aligned for the unknown pointee type.
It may be helpful to think of this type as similar to &'a dyn Any
but without
the metadata and able to point to data that does not correspond to a Rust type.
Implementations§
source§impl<'a> Ptr<'a>
impl<'a> Ptr<'a>
sourcepub fn to_unaligned(self) -> Ptr<'a, Unaligned>
pub fn to_unaligned(self) -> Ptr<'a, Unaligned>
Removes the alignment requirement of this pointer
source§impl<A> Ptr<'_, A>where
A: IsAligned,
impl<A> Ptr<'_, A>where
A: IsAligned,
sourcepub unsafe fn byte_offset(self, count: isize) -> Ptr<'_, A>
pub unsafe fn byte_offset(self, count: isize) -> Ptr<'_, A>
Calculates the offset from a pointer.
As the pointer is type-erased, there is no size information available. The provided
count
parameter is in raw bytes.
See also: ptr::offset
§Safety
- The offset cannot make the existing ptr null, or take it out of bounds for its allocation.
- If the
A
type parameter isAligned
then the offset must not make the resulting pointer be unaligned for the pointee type.
sourcepub unsafe fn byte_add(self, count: usize) -> Ptr<'_, A>
pub unsafe fn byte_add(self, count: usize) -> Ptr<'_, A>
Calculates the offset from a pointer (convenience for .offset(count as isize)
).
As the pointer is type-erased, there is no size information available. The provided
count
parameter is in raw bytes.
See also: ptr::add
§Safety
- The offset cannot make the existing ptr null, or take it out of bounds for its allocation.
- If the
A
type parameter isAligned
then the offset must not make the resulting pointer be unaligned for the pointee type.
source§impl<'a, A> Ptr<'a, A>where
A: IsAligned,
impl<'a, A> Ptr<'a, A>where
A: IsAligned,
sourcepub unsafe fn new(inner: NonNull<u8>) -> Ptr<'a, A>
pub unsafe fn new(inner: NonNull<u8>) -> Ptr<'a, A>
Creates a new instance from a raw pointer.
§Safety
inner
must point to valid value of whatever the pointee type is.- If the
A
type parameter isAligned
theninner
must be sufficiently aligned for the pointee type. inner
must have correct provenance to allow reads of the pointee type.- The lifetime
'a
must be constrained such that thisPtr
will stay valid and nothing can mutate the pointee while thisPtr
is live except through anUnsafeCell
.
sourcepub unsafe fn assert_unique(self) -> PtrMut<'a, A>
pub unsafe fn assert_unique(self) -> PtrMut<'a, A>
Transforms this Ptr
into an PtrMut
§Safety
Another PtrMut
for the same Ptr
must not be created until the first is dropped.
Examples found in repository?
45 46 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
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,
}
}
}
Trait Implementations§
impl<'a, A> Copy for Ptr<'a, A>
Auto Trait Implementations§
impl<'a, A> Freeze for Ptr<'a, A>where
A: Sealed,
impl<'a, A> RefUnwindSafe for Ptr<'a, A>where
A: Sealed + RefUnwindSafe,
impl<'a, A = Aligned> !Send for Ptr<'a, A>
impl<'a, A = Aligned> !Sync for Ptr<'a, A>
impl<'a, A> Unpin for Ptr<'a, A>where
A: Sealed + Unpin,
impl<'a, A> UnwindSafe for Ptr<'a, A>where
A: Sealed + UnwindSafe,
Blanket Implementations§
source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> 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
source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
source§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
.source§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
.source§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.source§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.