1use std::collections::HashMap;
2use std::ptr::NonNull;
3
4use crate::{trace, InitMark, ShapeDesc, Shapely};
5
6enum Destination<'s> {
8 Ptr {
13 ptr: NonNull<u8>,
14 init_mark: InitMark<'s>,
15 },
16
17 HashMap { map: NonNull<u8>, key: String },
19}
20
21pub struct Slot<'s> {
23 dest: Destination<'s>,
25
26 shape: ShapeDesc,
28}
29
30impl<'s> Slot<'s> {
31 #[inline(always)]
34 pub fn for_ptr(ptr: NonNull<u8>, shape: ShapeDesc, init_mark: InitMark<'s>) -> Self {
35 Self {
36 dest: Destination::Ptr { ptr, init_mark },
37 shape,
38 }
39 }
40
41 #[inline(always)]
44 pub fn for_hash_map(map: NonNull<u8>, key: String, shape: ShapeDesc) -> Self {
45 Self {
46 dest: Destination::HashMap { map, key },
47 shape,
48 }
49 }
50
51 pub fn fill<T: Shapely>(self, value: T) {
56 if self.shape != T::shape_desc() {
58 panic!(
59 "Attempted to fill a field with an incompatible shape.\n\
60 Expected shape: \x1b[33m{:?}\x1b[0m\n\
61 Actual shape: \x1b[33m{:?}\x1b[0m\n\
62 This is undefined behavior and we're refusing to proceed.",
63 self.shape.get(),
64 T::shape()
65 );
66 }
67 trace!(
68 "Filling slot with value of type: \x1b[33m{}\x1b[0m",
69 std::any::type_name::<T>()
70 );
71
72 match self.dest {
73 Destination::Ptr { ptr, mut init_mark } => {
74 if init_mark.get() {
75 trace!("Field already initialized, dropping existing value");
76 if let Some(drop_fn) = self.shape.get().drop_in_place {
77 unsafe {
82 drop_fn(ptr.as_ptr());
83 }
84 }
85 }
86
87 trace!("Filling struct field at address: \x1b[33m{:?}\x1b[0m", ptr);
88 unsafe { std::ptr::write(ptr.as_ptr() as *mut T, value) };
89 init_mark.set();
90 }
91 Destination::HashMap { map, key } => {
92 let map = unsafe { &mut *(map.as_ptr() as *mut HashMap<String, T>) };
93 trace!("Inserting value into HashMap with key: \x1b[33m{key}\x1b[0m");
94 map.insert(key, value);
95 }
96 }
97 }
98
99 pub fn fill_from_partial(self, partial: crate::Partial<'_>) {
100 if self.shape != partial.shape() {
101 panic!(
102 "Attempted to fill a field with an incompatible shape.\n\
103 Expected shape: {:?}\n\
104 Actual shape: {:?}\n\
105 This is undefined behavior and we're refusing to proceed.",
106 self.shape.get(),
107 partial.shape().get()
108 );
109 }
110
111 unsafe {
112 match self.dest {
113 Destination::Ptr { ptr, mut init_mark } => {
114 if init_mark.get() {
115 if let Some(drop_fn) = self.shape.get().drop_in_place {
116 drop_fn(ptr.as_ptr());
117 }
118 }
119 partial.move_into(ptr);
120 init_mark.set();
121 }
122 Destination::HashMap { map: _, ref key } => {
123 trace!(
124 "Filling HashMap entry: key=\x1b[33m{}\x1b[0m, src=\x1b[33m{:?}\x1b[0m, size=\x1b[33m{}\x1b[0m bytes",
125 key,
126 partial.addr.as_ptr(),
127 self.shape.get().layout.size()
128 );
129 panic!("fill_from_partial not implemented for HashMap");
132 }
133 }
134 }
135 }
136
137 pub fn shape(&self) -> ShapeDesc {
138 self.shape
139 }
140}