1use std::{
4 alloc::handle_alloc_error,
5 any::{type_name, TypeId},
6 ffi::c_void,
7 hash::Hash,
8 iter::{Filter, Map},
9 marker::PhantomData,
10 mem::MaybeUninit,
11 ptr::NonNull,
12 str::Split,
13 sync::OnceLock,
14};
15
16use bones_utils::prelude::*;
17use parking_lot::RwLock;
18use ustr::Ustr;
19
20use crate::{
21 prelude::*,
22 raw_fns::{RawClone, RawDefault, RawDrop},
23};
24
25#[derive(Clone, Copy)]
28pub struct SchemaRef<'pointer> {
29 ptr: NonNull<c_void>,
30 schema: &'static Schema,
31 _phantom: PhantomData<&'pointer ()>,
32}
33
34impl<'pointer> SchemaRef<'pointer> {
35 pub unsafe fn cast_unchecked<T>(&self) -> &T {
39 self.ptr.cast::<T>().as_ref()
40 }
41
42 pub unsafe fn cast_into_unchecked<T>(self) -> &'pointer T {
46 self.ptr.cast::<T>().as_ref()
47 }
48
49 #[track_caller]
55 pub fn cast<T: HasSchema>(&self) -> &'pointer T {
56 self.try_cast().expect(SchemaMismatchError::MSG)
57 }
58
59 pub fn try_cast<T: HasSchema>(&self) -> Result<&'pointer T, SchemaMismatchError> {
65 if self.schema.represents(T::schema()) {
66 Ok(unsafe { self.cast_into_unchecked() })
68 } else {
69 Err(SchemaMismatchError)
70 }
71 }
72
73 pub fn new<T: HasSchema>(v: &'pointer T) -> SchemaRef<'pointer> {
75 let schema = T::schema();
76 SchemaRef {
77 ptr: unsafe { NonNull::new_unchecked(v as *const T as *mut c_void) },
79 schema,
80 _phantom: PhantomData,
81 }
82 }
83
84 #[track_caller]
91 pub unsafe fn from_ptr_schema(ptr: *const c_void, schema: &'static Schema) -> Self {
92 Self {
93 ptr: NonNull::new_unchecked(ptr as *mut c_void),
94 schema,
95 _phantom: PhantomData,
96 }
97 }
98
99 pub fn as_ptr(&self) -> *const c_void {
101 self.ptr.as_ptr()
102 }
103
104 pub fn schema(&self) -> &'static Schema {
106 self.schema
107 }
108
109 pub fn hash(&self) -> Option<u64> {
111 self.schema
112 .hash_fn
113 .as_ref()
114 .map(|hash_fn| unsafe { (hash_fn.get())(self.ptr.as_ptr()) })
115 }
116
117 pub fn as_map(&self) -> Option<&'pointer SchemaMap> {
119 matches!(self.schema.kind, SchemaKind::Map { .. })
120 .then(|| unsafe { self.cast_into_unchecked::<SchemaMap>() })
122 }
123
124 pub fn as_vec(&self) -> Option<&'pointer SchemaVec> {
126 matches!(self.schema.kind, SchemaKind::Vec(_))
127 .then(|| unsafe { self.cast_into_unchecked::<SchemaVec>() })
129 }
130
131 pub fn as_box(&self) -> Option<SchemaRef<'pointer>> {
133 matches!(self.schema.kind, SchemaKind::Vec(_))
134 .then(|| unsafe { self.cast_into_unchecked::<SchemaBox>().as_ref() })
136 }
137
138 pub fn debug_format_value(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
142 f.write_fmt(format_args!("{:?}", self.access_borrowed()))
143 }
144
145 pub fn access(self) -> SchemaRefAccess<'pointer> {
147 SchemaRefAccess::new(self)
148 }
149
150 fn access_borrowed(&self) -> SchemaRefAccess<'_> {
152 SchemaRefAccess::new_borrowed(self)
153 }
154
155 pub fn field<'a, I: Into<FieldIdx<'a>>>(self, field_idx: I) -> Option<SchemaRef<'pointer>> {
157 Some(self.access().field(field_idx)?.into_schema_ref())
158 }
159
160 pub fn field_path<'a, I: IntoIterator<Item = FieldIdx<'a>>>(self, path: I) -> Option<Self> {
162 let mut current_field = self;
163 for field_idx in path {
164 current_field = current_field.field(field_idx)?;
165 }
166 Some(current_field)
167 }
168
169 pub fn clone_into_box(&self) -> SchemaBox {
171 let Some(clone_fn) = &self.schema.clone_fn else {
172 panic!(
173 "The schema for type `{}` does not allow cloning it.",
174 self.schema.full_name
175 );
176 };
177 unsafe {
178 let b = SchemaBox::uninitialized(self.schema);
179 (clone_fn.get())(self.ptr.as_ptr(), b.ptr.as_ptr());
180 b
181 }
182 }
183}
184
185struct SchemaRefValueDebug<'a>(SchemaRef<'a>);
186impl std::fmt::Debug for SchemaRefValueDebug<'_> {
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 self.0.debug_format_value(f)
189 }
190}
191
192impl std::fmt::Debug for SchemaRef<'_> {
193 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194 f.debug_tuple("SchemaRef<'_>")
195 .field(&SchemaRefValueDebug(*self))
196 .finish()
197 }
198}
199impl std::fmt::Display for SchemaRef<'_> {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 <SchemaRefValueDebug as std::fmt::Debug>::fmt(&SchemaRefValueDebug(*self), f)
202 }
203}
204
205#[derive(Clone, Copy)]
207pub enum SchemaRefAccess<'a> {
208 Struct(StructRefAccess<'a>),
210 Vec(SchemaVecAccess<'a>),
212 Enum(EnumRefAccess<'a>),
214 Map(SchemaMapAccess<'a>),
216 Primitive(PrimitiveRef<'a>),
218}
219
220impl std::fmt::Debug for SchemaRefAccess<'_> {
221 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
222 match self {
223 SchemaRefAccess::Struct(s) => {
224 let is_tuple = s.fields().any(|x| x.name.is_none());
225 if is_tuple {
226 let mut builder = f.debug_tuple(&s.schema().name);
227 for field in s.fields() {
228 builder.field(&SchemaRefValueDebug(field.value));
229 }
230 builder.finish()
231 } else {
232 let mut builder = f.debug_struct(&s.schema().name);
233 for field in s.fields() {
234 builder.field(field.name.unwrap(), &SchemaRefValueDebug(field.value));
235 }
236 builder.finish()
237 }
238 }
239 SchemaRefAccess::Vec(v) => {
240 let mut builder = f.debug_list();
241 for item in v.iter() {
242 builder.entry(&SchemaRefValueDebug(item));
243 }
244 builder.finish()
245 }
246 SchemaRefAccess::Enum(e) => {
247 f.write_fmt(format_args!("{:?}", SchemaRefValueDebug(e.value().0)))
248 }
249 SchemaRefAccess::Map(m) => {
250 let mut builder = f.debug_map();
251 for (key, value) in m.iter() {
252 builder.key(&SchemaRefValueDebug(key));
253 builder.value(&SchemaRefValueDebug(value));
254 }
255 builder.finish()
256 }
257 SchemaRefAccess::Primitive(p) => match p {
258 PrimitiveRef::Bool(b) => f.write_fmt(format_args!("{b}")),
259 PrimitiveRef::U8(n) => f.write_fmt(format_args!("{n}")),
260 PrimitiveRef::U16(n) => f.write_fmt(format_args!("{n}")),
261 PrimitiveRef::U32(n) => f.write_fmt(format_args!("{n}")),
262 PrimitiveRef::U64(n) => f.write_fmt(format_args!("{n}")),
263 PrimitiveRef::U128(n) => f.write_fmt(format_args!("{n}")),
264 PrimitiveRef::I8(n) => f.write_fmt(format_args!("{n}")),
265 PrimitiveRef::I16(n) => f.write_fmt(format_args!("{n}")),
266 PrimitiveRef::I32(n) => f.write_fmt(format_args!("{n}")),
267 PrimitiveRef::I64(n) => f.write_fmt(format_args!("{n}")),
268 PrimitiveRef::I128(n) => f.write_fmt(format_args!("{n}")),
269 PrimitiveRef::F32(n) => f.write_fmt(format_args!("{n}")),
270 PrimitiveRef::F64(n) => f.write_fmt(format_args!("{n}")),
271 PrimitiveRef::String(s) => f.write_fmt(format_args!("{s:?}")),
272 PrimitiveRef::Opaque {
273 size,
274 align,
275 schema_ref,
276 } => f
277 .debug_tuple(&schema_ref.schema.name)
278 .field(&Primitive::Opaque {
279 size: *size,
280 align: *align,
281 })
282 .finish(),
283 },
284 }
285 }
286}
287
288impl<'ptr> SchemaRefAccess<'ptr> {
289 pub fn new(value: SchemaRef) -> SchemaRefAccess {
295 match &value.schema.kind {
296 SchemaKind::Struct(_) => SchemaRefAccess::Struct(StructRefAccess(value)),
297 SchemaKind::Vec(_) => SchemaRefAccess::Vec(SchemaVecAccess {
298 vec: value.as_vec().unwrap(),
299 orig_ref: value,
300 }),
301 SchemaKind::Enum(_) => SchemaRefAccess::Enum(EnumRefAccess(value)),
302 SchemaKind::Map { .. } => SchemaRefAccess::Map(SchemaMapAccess {
303 map: value.as_map().unwrap(),
304 orig_ref: value,
305 }),
306 SchemaKind::Box(_) => value.as_box().unwrap().access(),
307 SchemaKind::Primitive(_) => SchemaRefAccess::Primitive(value.into()),
308 }
309 }
310
311 pub fn new_borrowed<'borrow>(value: &'borrow SchemaRef<'_>) -> SchemaRefAccess<'borrow> {
319 match &value.schema.kind {
320 SchemaKind::Struct(_) => SchemaRefAccess::Struct(StructRefAccess(*value)),
321 SchemaKind::Vec(_) => SchemaRefAccess::Vec(SchemaVecAccess {
322 vec: value.as_vec().unwrap(),
323 orig_ref: *value,
324 }),
325 SchemaKind::Enum(_) => SchemaRefAccess::Enum(EnumRefAccess(*value)),
326 SchemaKind::Map { .. } => SchemaRefAccess::Map(SchemaMapAccess {
327 map: value.as_map().unwrap(),
328 orig_ref: *value,
329 }),
330 SchemaKind::Box(_) => value.as_box().unwrap().access(),
331 SchemaKind::Primitive(_) => SchemaRefAccess::Primitive((*value).into()),
332 }
333 }
334
335 pub fn field<'a, I: Into<FieldIdx<'a>>>(self, field_idx: I) -> Option<Self> {
337 let field_idx = field_idx.into();
338 match self {
339 SchemaRefAccess::Struct(s) => s.field(field_idx),
340 SchemaRefAccess::Vec(_)
341 | SchemaRefAccess::Enum(_)
342 | SchemaRefAccess::Map(_)
343 | SchemaRefAccess::Primitive(_) => None,
344 }
345 }
346
347 pub fn field_path<'a, I: IntoIterator<Item = FieldIdx<'a>>>(self, path: I) -> Option<Self> {
349 let mut current_field = self;
350 for field_idx in path {
351 current_field = current_field.field(field_idx)?;
352 }
353 Some(current_field)
354 }
355
356 pub fn into_schema_ref(self) -> SchemaRef<'ptr> {
358 match self {
359 SchemaRefAccess::Struct(s) => s.0,
360 SchemaRefAccess::Vec(v) => v.into_schema_ref(),
361 SchemaRefAccess::Enum(e) => e.0,
362 SchemaRefAccess::Map(m) => m.into_schema_ref(),
363 SchemaRefAccess::Primitive(p) => p.into_schema_ref(),
364 }
365 }
366}
367
368#[derive(Deref, DerefMut, Clone, Copy)]
370pub struct SchemaVecAccess<'a> {
371 #[deref]
373 vec: &'a SchemaVec,
374 orig_ref: SchemaRef<'a>,
375}
376
377impl<'a> SchemaVecAccess<'a> {
378 pub fn into_schema_ref(self) -> SchemaRef<'a> {
380 self.orig_ref
381 }
382}
383
384#[derive(Deref, DerefMut, Clone, Copy)]
386pub struct SchemaMapAccess<'a> {
387 #[deref]
389 map: &'a SchemaMap,
390 orig_ref: SchemaRef<'a>,
391}
392
393impl<'a> SchemaMapAccess<'a> {
394 pub fn into_schema_ref(self) -> SchemaRef<'a> {
396 self.orig_ref
397 }
398}
399
400#[derive(Clone, Copy)]
402pub struct StructRefAccess<'a>(SchemaRef<'a>);
403
404impl<'a> StructRefAccess<'a> {
405 pub fn schema(&self) -> &'static Schema {
407 self.0.schema
408 }
409
410 pub fn info(&self) -> &'static StructSchemaInfo {
412 self.0.schema.kind.as_struct().unwrap()
413 }
414
415 pub fn fields(&self) -> StructRefFieldIter<'_> {
417 StructRefFieldIter {
418 ptr: self.0,
419 field_idx: 0,
420 }
421 }
422
423 pub fn field<'i, I: Into<FieldIdx<'i>>>(self, field_idx: I) -> Option<SchemaRefAccess<'a>> {
425 let field_idx = field_idx.into();
426 let field_idx = match field_idx {
427 FieldIdx::Name(name) => self
428 .info()
429 .fields
430 .iter()
431 .position(|x| x.name.as_ref().map(|x| x.as_ref()) == Some(name))?,
432 FieldIdx::Idx(idx) => idx,
433 };
434 let field_schema = self
435 .0
436 .schema
437 .kind
438 .as_struct()
439 .unwrap()
440 .fields
441 .get(field_idx)
442 .unwrap()
443 .schema;
444 let (_, field_offset) = self.0.schema.field_offsets().get(field_idx).unwrap();
445
446 Some(unsafe {
447 SchemaRef {
448 ptr: NonNull::new_unchecked(self.0.as_ptr().add(*field_offset) as *mut c_void),
449 schema: field_schema,
450 _phantom: PhantomData,
451 }
452 .access()
453 })
454 }
455
456 pub fn as_schema_ref(&self) -> SchemaRef<'a> {
458 self.0
459 }
460}
461
462pub struct StructRefFieldIter<'a> {
464 ptr: SchemaRef<'a>,
465 field_idx: usize,
466}
467
468pub struct StructRefFieldIterField<'a> {
470 pub name: Option<&'static str>,
472 pub value: SchemaRef<'a>,
474}
475
476impl<'a> Iterator for StructRefFieldIter<'a> {
477 type Item = StructRefFieldIterField<'a>;
478
479 fn next(&mut self) -> Option<Self::Item> {
480 let (name, _) = self.ptr.schema.field_offsets().get(self.field_idx)?;
481 let ptr = self
482 .ptr
483 .access()
484 .field(self.field_idx)
485 .unwrap()
486 .into_schema_ref();
487 self.field_idx += 1;
488 Some(StructRefFieldIterField {
489 name: name.as_ref().map(|x| x.as_str()),
490 value: ptr,
491 })
492 }
493}
494
495#[derive(Clone, Copy)]
497pub struct EnumRefAccess<'a>(pub SchemaRef<'a>);
498
499impl<'a> EnumRefAccess<'a> {
500 pub fn schema(&self) -> &'static Schema {
502 self.0.schema
503 }
504
505 pub fn info(&self) -> &'static EnumSchemaInfo {
507 let SchemaKind::Enum(info) = &self.0.schema.kind else {
508 panic!("Not an enum");
509 };
510 info
511 }
512
513 pub fn variant_info(&self) -> &'static VariantInfo {
515 &self.info().variants[self.variant_idx() as usize]
516 }
517
518 pub fn variant_struct_info(&self) -> &'static StructSchemaInfo {
520 self.variant_info().schema.kind.as_struct().unwrap()
521 }
522
523 pub fn variant_idx(&self) -> u32 {
525 let info = self.info();
526 match info.tag_type {
527 EnumTagType::U8 => unsafe { self.0.as_ptr().cast::<u8>().read() as u32 },
528 EnumTagType::U16 => unsafe { self.0.as_ptr().cast::<u16>().read() as u32 },
529 EnumTagType::U32 => unsafe { self.0.as_ptr().cast::<u32>().read() },
530 }
531 }
532
533 pub fn variant_name(&self) -> &'static str {
535 let info = self.info();
536 let idx = self.variant_idx();
537 info.variants[idx as usize].name.as_ref()
538 }
539
540 pub fn value(&self) -> StructRefAccess<'a> {
542 let info = self.info();
543 let variant_idx = self.variant_idx();
544 let variant_info = &info.variants[variant_idx as usize];
545 let schema = variant_info.schema;
546 let value_offset = self.0.schema.field_offsets()[0].1;
547 StructRefAccess(SchemaRef {
548 ptr: unsafe { NonNull::new_unchecked(self.0.ptr.as_ptr().add(value_offset)) },
549 schema,
550 _phantom: PhantomData,
551 })
552 }
553}
554
555#[derive(Clone, Copy, Debug)]
557pub enum PrimitiveRef<'a> {
558 Bool(&'a bool),
560 U8(&'a u8),
562 U16(&'a u16),
564 U32(&'a u32),
566 U64(&'a u64),
568 U128(&'a u128),
570 I8(&'a i8),
572 I16(&'a i16),
574 I32(&'a i32),
576 I64(&'a i64),
578 I128(&'a i128),
580 F32(&'a f32),
582 F64(&'a f64),
584 String(&'a String),
586 Opaque {
588 size: usize,
590 align: usize,
592 schema_ref: SchemaRef<'a>,
594 },
595}
596
597impl<'ptr> PrimitiveRef<'ptr> {
598 fn into_schema_ref(self) -> SchemaRef<'ptr> {
599 match self {
600 PrimitiveRef::Bool(b) => SchemaRef::new(b),
601 PrimitiveRef::U8(n) => SchemaRef::new(n),
602 PrimitiveRef::U16(n) => SchemaRef::new(n),
603 PrimitiveRef::U32(n) => SchemaRef::new(n),
604 PrimitiveRef::U64(n) => SchemaRef::new(n),
605 PrimitiveRef::U128(n) => SchemaRef::new(n),
606 PrimitiveRef::I8(n) => SchemaRef::new(n),
607 PrimitiveRef::I16(n) => SchemaRef::new(n),
608 PrimitiveRef::I32(n) => SchemaRef::new(n),
609 PrimitiveRef::I64(n) => SchemaRef::new(n),
610 PrimitiveRef::I128(n) => SchemaRef::new(n),
611 PrimitiveRef::F32(n) => SchemaRef::new(n),
612 PrimitiveRef::F64(n) => SchemaRef::new(n),
613 PrimitiveRef::String(s) => SchemaRef::new(s),
614 PrimitiveRef::Opaque { schema_ref, .. } => schema_ref,
615 }
616 }
617}
618
619impl<'a> From<SchemaRef<'a>> for PrimitiveRef<'a> {
620 fn from(value: SchemaRef<'a>) -> Self {
621 match &value.schema.kind {
622 SchemaKind::Primitive(p) => match p {
623 Primitive::Bool => PrimitiveRef::Bool(value.cast()),
624 Primitive::U8 => PrimitiveRef::U8(value.cast()),
625 Primitive::U16 => PrimitiveRef::U16(value.cast()),
626 Primitive::U32 => PrimitiveRef::U32(value.cast()),
627 Primitive::U64 => PrimitiveRef::U64(value.cast()),
628 Primitive::U128 => PrimitiveRef::U128(value.cast()),
629 Primitive::I8 => PrimitiveRef::I8(value.cast()),
630 Primitive::I16 => PrimitiveRef::I16(value.cast()),
631 Primitive::I32 => PrimitiveRef::I32(value.cast()),
632 Primitive::I64 => PrimitiveRef::I64(value.cast()),
633 Primitive::I128 => PrimitiveRef::I128(value.cast()),
634 Primitive::F32 => PrimitiveRef::F32(value.cast()),
635 Primitive::F64 => PrimitiveRef::F64(value.cast()),
636 Primitive::String => PrimitiveRef::String(value.cast()),
637 Primitive::Opaque { size, align } => PrimitiveRef::Opaque {
638 size: *size,
639 align: *align,
640 schema_ref: value,
641 },
642 },
643 _ => panic!("Schema mismatch"),
644 }
645 }
646}
647
648pub struct SchemaRefMut<'pointer> {
651 ptr: NonNull<c_void>,
652 schema: &'static Schema,
653 _phantom: PhantomData<&'pointer mut ()>,
654}
655
656impl<'pointer> std::fmt::Debug for SchemaRefMut<'pointer> {
657 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
658 f.debug_struct("SchemaRefMut")
659 .field("schema", &self.schema)
661 .finish()
663 }
664}
665
666impl<'pointer> SchemaRefMut<'pointer> {
667 pub unsafe fn cast_mut_unchecked<T>(&mut self) -> &mut T {
671 self.ptr.cast::<T>().as_mut()
672 }
673
674 pub unsafe fn cast_into_mut_unchecked<T>(self) -> &'pointer mut T {
678 self.ptr.cast::<T>().as_mut()
679 }
680
681 #[track_caller]
687 pub fn cast_mut<T: HasSchema + 'static>(&mut self) -> &mut T {
688 self.try_cast_mut().expect(SchemaMismatchError::MSG)
689 }
690
691 pub fn try_cast_mut<T: HasSchema>(&mut self) -> Result<&mut T, SchemaMismatchError> {
696 if self.schema.represents(T::schema()) {
697 unsafe { Ok(self.ptr.cast::<T>().as_mut()) }
699 } else {
700 Err(SchemaMismatchError)
701 }
702 }
703
704 #[inline]
712 pub fn cast_into_mut<T: HasSchema>(self) -> &'pointer mut T {
713 self.try_cast_into_mut().unwrap()
714 }
715
716 pub fn try_cast_into_mut<T: HasSchema>(self) -> Result<&'pointer mut T, SchemaMismatchError> {
724 if self.schema.represents(T::schema()) {
725 Ok(unsafe { self.ptr.cast::<T>().as_mut() })
727 } else {
728 Err(SchemaMismatchError)
729 }
730 }
731
732 pub fn new<T: HasSchema>(v: &'pointer mut T) -> SchemaRefMut<'pointer> {
734 let schema = T::schema();
735 SchemaRefMut {
736 ptr: unsafe { NonNull::new_unchecked(v as *mut T as *mut c_void) },
738 schema,
739 _phantom: PhantomData,
740 }
741 }
742
743 pub unsafe fn from_ptr_schema(
750 ptr: *mut c_void,
751 schema: &'static Schema,
752 ) -> SchemaRefMut<'pointer> {
753 Self {
754 ptr: NonNull::new_unchecked(ptr),
755 schema,
756 _phantom: PhantomData,
757 }
758 }
759
760 pub fn into_map(self) -> Result<&'pointer mut SchemaMap, Self> {
762 matches!(self.schema.kind, SchemaKind::Map { .. })
763 .then(|| unsafe { &mut *(self.ptr.as_ptr() as *mut SchemaMap) })
765 .ok_or(self)
766 }
767
768 pub fn into_vec(self) -> Result<&'pointer mut SchemaVec, Self> {
770 matches!(self.schema.kind, SchemaKind::Vec(_))
771 .then(|| unsafe { &mut *(self.ptr.as_ptr() as *mut SchemaVec) })
773 .ok_or(self)
774 }
775
776 pub fn into_box(self) -> Result<SchemaRefMut<'pointer>, Self> {
778 matches!(self.schema.kind, SchemaKind::Vec(_))
779 .then(|| unsafe { (*(self.ptr.as_ptr() as *mut SchemaBox)).as_mut() })
781 .ok_or(self)
782 }
783
784 pub fn into_access_mut(self) -> SchemaRefMutAccess<'pointer> {
786 SchemaRefMutAccess::new(self)
787 }
788
789 pub fn access_mut(&mut self) -> SchemaRefMutAccess<'_> {
791 SchemaRefMutAccess::new_borrowed(self)
792 }
793
794 pub fn as_ptr(&self) -> *mut c_void {
796 self.ptr.as_ptr()
797 }
798
799 pub fn schema(&self) -> &'static Schema {
801 self.schema
802 }
803
804 pub fn hash(&self) -> Option<u64> {
806 self.schema
807 .hash_fn
808 .as_ref()
809 .map(|hash_fn| unsafe { (hash_fn.get())(self.ptr.as_ptr()) })
810 }
811
812 pub fn as_ref(&self) -> SchemaRef<'_> {
814 SchemaRef {
815 ptr: self.ptr,
816 schema: self.schema,
817 _phantom: PhantomData,
818 }
819 }
820
821 pub fn reborrow(&mut self) -> SchemaRefMut<'_> {
824 SchemaRefMut {
825 ptr: self.ptr,
826 schema: self.schema,
827 _phantom: PhantomData,
828 }
829 }
830
831 pub fn field<'a, I: Into<FieldIdx<'a>>>(&mut self, field_idx: I) -> Option<SchemaRefMut<'_>> {
833 Some(
834 self.access_mut()
835 .field(field_idx)
836 .ok()?
837 .into_schema_ref_mut(),
838 )
839 }
840
841 pub fn field_path<'a, I: IntoIterator<Item = FieldIdx<'a>>>(
843 &mut self,
844 path: I,
845 ) -> Option<SchemaRefMut<'_>> {
846 self.access_mut()
847 .field_path(path)
848 .map(|x| x.into_schema_ref_mut())
849 }
850
851 pub fn into_field_path<'a, I: IntoIterator<Item = FieldIdx<'a>>>(
853 self,
854 path: I,
855 ) -> Option<Self> {
856 self.into_access_mut()
857 .field_path(path)
858 .map(|x| x.into_schema_ref_mut())
859 }
860
861 pub fn into_field<'a, I: Into<FieldIdx<'a>>>(
863 self,
864 field_idx: I,
865 ) -> Result<SchemaRefMut<'pointer>, Self> {
866 self.into_access_mut()
867 .field(field_idx)
868 .map(|x| x.into_schema_ref_mut())
869 .map_err(|access| access.into_schema_ref_mut())
870 }
871
872 pub fn write(&mut self, other: SchemaRef) -> Result<(), SchemaMismatchError> {
874 if self.schema == other.schema {
875 let clone_fn = self.schema.clone_fn.as_ref().unwrap_or_else(|| {
876 panic!(
877 "Schema does not provide clone fn: {}",
878 self.schema.full_name
879 )
880 });
881 unsafe { clone_fn.get()(other.as_ptr(), self.as_ptr()) }
883 Ok(())
884 } else {
885 Err(SchemaMismatchError)
886 }
887 }
888}
889
890pub enum SchemaRefMutAccess<'a> {
892 Struct(StructRefMutAccess<'a>),
894 Vec(SchemaVecMutAccess<'a>),
896 Enum(EnumRefMutAccess<'a>),
898 Map(SchemaMapMutAccess<'a>),
900 Primitive(PrimitiveRefMut<'a>),
902}
903
904#[derive(Deref, DerefMut)]
906pub struct SchemaVecMutAccess<'a> {
907 #[deref]
909 vec: &'a mut SchemaVec,
910 orig_ptr: *mut c_void,
914 orig_schema: &'static Schema,
915}
916
917impl<'a> SchemaVecMutAccess<'a> {
918 pub fn as_mut(self) -> SchemaRefMut<'a> {
920 unsafe { SchemaRefMut::from_ptr_schema(self.orig_ptr, self.orig_schema) }
923 }
924}
925
926#[derive(Deref, DerefMut)]
928pub struct SchemaMapMutAccess<'a> {
929 #[deref]
931 map: &'a mut SchemaMap,
932 orig_ptr: *mut c_void,
936 orig_schema: &'static Schema,
937}
938
939impl<'a> SchemaMapMutAccess<'a> {
940 pub fn into_schema_ref_mut(self) -> SchemaRefMut<'a> {
942 unsafe { SchemaRefMut::from_ptr_schema(self.orig_ptr, self.orig_schema) }
945 }
946}
947
948impl std::fmt::Debug for SchemaRefMutAccess<'_> {
949 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
950 self.as_ref().fmt(f)
951 }
952}
953
954impl<'pointer> SchemaRefMutAccess<'pointer> {
955 pub fn new(value: SchemaRefMut) -> SchemaRefMutAccess {
961 match &value.schema.kind {
962 SchemaKind::Struct(_) => SchemaRefMutAccess::Struct(StructRefMutAccess(value)),
963 SchemaKind::Vec(_) => SchemaRefMutAccess::Vec(SchemaVecMutAccess {
964 orig_ptr: value.as_ptr(),
965 orig_schema: value.schema,
966 vec: value.into_vec().unwrap(),
967 }),
968 SchemaKind::Enum(_) => SchemaRefMutAccess::Enum(EnumRefMutAccess(value)),
969 SchemaKind::Map { .. } => SchemaRefMutAccess::Map(SchemaMapMutAccess {
970 orig_ptr: value.as_ptr(),
971 orig_schema: value.schema,
972 map: value.into_map().unwrap(),
973 }),
974 SchemaKind::Box(_) => value.into_box().unwrap().into_access_mut(),
975 SchemaKind::Primitive(_) => SchemaRefMutAccess::Primitive(value.into()),
976 }
977 }
978
979 pub fn new_borrowed<'borrow>(
987 value: &'borrow mut SchemaRefMut<'_>,
988 ) -> SchemaRefMutAccess<'borrow> {
989 match &value.schema.kind {
990 SchemaKind::Struct(_) => {
991 SchemaRefMutAccess::Struct(StructRefMutAccess(value.reborrow()))
992 }
993 SchemaKind::Vec(_) => SchemaRefMutAccess::Vec(SchemaVecMutAccess {
994 orig_ptr: value.as_ptr(),
995 orig_schema: value.schema,
996 vec: value.reborrow().into_vec().unwrap(),
997 }),
998 SchemaKind::Enum(_) => SchemaRefMutAccess::Enum(EnumRefMutAccess(value.reborrow())),
999 SchemaKind::Map { .. } => SchemaRefMutAccess::Map(SchemaMapMutAccess {
1000 orig_ptr: value.as_ptr(),
1001 orig_schema: value.schema,
1002 map: value.reborrow().into_map().unwrap(),
1003 }),
1004 SchemaKind::Box(_) => value.reborrow().into_box().unwrap().into_access_mut(),
1005 SchemaKind::Primitive(_) => SchemaRefMutAccess::Primitive(value.reborrow().into()),
1006 }
1007 }
1008
1009 pub fn into_schema_ref_mut(self) -> SchemaRefMut<'pointer> {
1011 match self {
1012 SchemaRefMutAccess::Struct(s) => s.0,
1013 SchemaRefMutAccess::Vec(v) => v.as_mut(),
1014 SchemaRefMutAccess::Enum(e) => e.0,
1015 SchemaRefMutAccess::Map(m) => m.into_schema_ref_mut(),
1016 SchemaRefMutAccess::Primitive(p) => p.into_schema_ref_mut(),
1017 }
1018 }
1019
1020 pub fn field<'a, I: Into<FieldIdx<'a>>>(self, field_idx: I) -> Result<Self, Self> {
1022 let field_idx = field_idx.into();
1023 match self {
1024 SchemaRefMutAccess::Struct(s) => {
1025 s.into_field(field_idx).map_err(SchemaRefMutAccess::Struct)
1026 }
1027 other @ (SchemaRefMutAccess::Vec(_)
1028 | SchemaRefMutAccess::Enum(_)
1029 | SchemaRefMutAccess::Map(_)
1030 | SchemaRefMutAccess::Primitive(_)) => Err(other),
1031 }
1032 }
1033
1034 pub fn field_path<'a, I: IntoIterator<Item = FieldIdx<'a>>>(self, path: I) -> Option<Self> {
1036 let mut current_field = self;
1037 for field_idx in path {
1038 current_field = current_field.field(field_idx).ok()?;
1039 }
1040 Some(current_field)
1041 }
1042
1043 pub fn as_ref(&self) -> SchemaRefAccess<'_> {
1045 match self {
1046 SchemaRefMutAccess::Struct(s) => SchemaRefAccess::Struct(StructRefAccess(s.0.as_ref())),
1047 SchemaRefMutAccess::Vec(v) => SchemaRefAccess::Vec(SchemaVecAccess {
1048 vec: &*v.vec,
1049 orig_ref: unsafe {
1051 SchemaRef::from_ptr_schema(
1052 (&*v.vec) as *const SchemaVec as *const c_void,
1053 v.orig_schema,
1054 )
1055 },
1056 }),
1057 SchemaRefMutAccess::Enum(e) => SchemaRefAccess::Enum(EnumRefAccess(e.0.as_ref())),
1058 SchemaRefMutAccess::Map(m) => SchemaRefAccess::Map(SchemaMapAccess {
1059 map: &*m.map,
1060 orig_ref: unsafe {
1062 SchemaRef::from_ptr_schema(
1063 (&*m.map) as *const SchemaMap as *const c_void,
1064 m.orig_schema,
1065 )
1066 },
1067 }),
1068 SchemaRefMutAccess::Primitive(p) => SchemaRefAccess::Primitive(p.as_ref()),
1069 }
1070 }
1071}
1072
1073pub struct StructRefMutAccess<'a>(pub SchemaRefMut<'a>);
1075
1076impl<'a> StructRefMutAccess<'a> {
1077 pub fn schema(&self) -> &'static Schema {
1079 self.0.schema
1080 }
1081
1082 pub fn info(&self) -> &'static StructSchemaInfo {
1084 self.0.schema.kind.as_struct().unwrap()
1085 }
1086
1087 pub fn into_field<'i, I: Into<FieldIdx<'i>>>(
1089 self,
1090 field_idx: I,
1091 ) -> Result<SchemaRefMutAccess<'a>, Self> {
1092 let field_idx = field_idx.into();
1093 let field_idx = match field_idx {
1094 FieldIdx::Name(name) => {
1095 if let Some(idx) = self
1096 .info()
1097 .fields
1098 .iter()
1099 .position(|x| x.name.as_ref().map(|x| x.as_ref()) == Some(name))
1100 {
1101 idx
1102 } else {
1103 return Err(self);
1104 }
1105 }
1106 FieldIdx::Idx(idx) => idx,
1107 };
1108 let field_schema = self
1109 .0
1110 .schema
1111 .kind
1112 .as_struct()
1113 .unwrap()
1114 .fields
1115 .get(field_idx)
1116 .unwrap()
1117 .schema;
1118 let (_, field_offset) = self.0.schema.field_offsets().get(field_idx).unwrap();
1119
1120 Ok(unsafe {
1121 SchemaRefMut {
1122 ptr: NonNull::new_unchecked(self.0.as_ptr().add(*field_offset)),
1123 schema: field_schema,
1124 _phantom: PhantomData,
1125 }
1126 .into_access_mut()
1127 })
1128 }
1129
1130 pub fn fields(&mut self) -> StructRefMutFieldIter<'_> {
1132 StructRefMutFieldIter {
1133 ptr: self.0.reborrow(),
1134 field_idx: 0,
1135 }
1136 }
1137
1138 pub fn into_fields(self) -> StructRefMutFieldIter<'a> {
1140 StructRefMutFieldIter {
1141 ptr: self.0,
1142 field_idx: 0,
1143 }
1144 }
1145}
1146
1147pub struct StructRefMutFieldIter<'a> {
1149 ptr: SchemaRefMut<'a>,
1150 field_idx: usize,
1151}
1152
1153pub struct StructRefMutFieldIterField<'a> {
1155 pub name: Option<&'static str>,
1157 pub value: SchemaRefMut<'a>,
1159}
1160
1161impl<'a> Iterator for StructRefMutFieldIter<'a> {
1162 type Item = StructRefMutFieldIterField<'a>;
1163
1164 fn next(&mut self) -> Option<Self::Item> {
1165 let field_schema = self
1166 .ptr
1167 .schema
1168 .kind
1169 .as_struct()
1170 .unwrap()
1171 .fields
1172 .get(self.field_idx)?
1173 .schema;
1174 let (name, field_offset) = self.ptr.schema.field_offsets().get(self.field_idx)?;
1175 self.field_idx += 1;
1176
1177 Some(StructRefMutFieldIterField {
1178 name: name.as_ref().map(|x| x.as_str()),
1179 value: unsafe {
1182 SchemaRefMut {
1183 ptr: NonNull::new_unchecked(self.ptr.as_ptr().add(*field_offset)),
1184 schema: field_schema,
1185 _phantom: PhantomData,
1186 }
1187 },
1188 })
1189 }
1190}
1191
1192pub struct EnumRefMutAccess<'a>(pub SchemaRefMut<'a>);
1194
1195impl<'a> EnumRefMutAccess<'a> {
1196 pub fn schema(&self) -> &'static Schema {
1198 self.0.schema
1199 }
1200
1201 pub fn info(&self) -> &'static EnumSchemaInfo {
1203 let SchemaKind::Enum(info) = &self.0.schema.kind else {
1204 panic!("Not an enum");
1205 };
1206 info
1207 }
1208
1209 pub fn variant_idx(&self) -> u32 {
1211 let info = self.info();
1212 match info.tag_type {
1213 EnumTagType::U8 => unsafe { self.0.as_ptr().cast::<u8>().read() as u32 },
1214 EnumTagType::U16 => unsafe { self.0.as_ptr().cast::<u16>().read() as u32 },
1215 EnumTagType::U32 => unsafe { self.0.as_ptr().cast::<u32>().read() },
1216 }
1217 }
1218
1219 pub fn variant_name(&self) -> &'static str {
1221 let info = self.info();
1222 let idx = self.variant_idx();
1223 info.variants[idx as usize].name.as_ref()
1224 }
1225
1226 pub fn value(&self) -> StructRefMutAccess<'a> {
1228 let info = self.info();
1229 let variant_idx = self.variant_idx();
1230 let variant_info = &info.variants[variant_idx as usize];
1231 let schema = variant_info.schema;
1232 let value_offset = self.0.schema.field_offsets()[0].1;
1233 StructRefMutAccess(SchemaRefMut {
1234 ptr: unsafe { NonNull::new_unchecked(self.0.ptr.as_ptr().add(value_offset)) },
1235 schema,
1236 _phantom: PhantomData,
1237 })
1238 }
1239}
1240
1241pub enum PrimitiveRefMut<'a> {
1243 Bool(&'a mut bool),
1245 U8(&'a mut u8),
1247 U16(&'a mut u16),
1249 U32(&'a mut u32),
1251 U64(&'a mut u64),
1253 U128(&'a mut u128),
1255 I8(&'a mut i8),
1257 I16(&'a mut i16),
1259 I32(&'a mut i32),
1261 I64(&'a mut i64),
1263 I128(&'a mut i128),
1265 F32(&'a mut f32),
1267 F64(&'a mut f64),
1269 String(&'a mut String),
1271 Opaque {
1273 size: usize,
1275 align: usize,
1277 schema_ref: SchemaRefMut<'a>,
1279 },
1280}
1281
1282impl<'ptr> PrimitiveRefMut<'ptr> {
1283 pub fn as_ref(&self) -> PrimitiveRef<'_> {
1285 match self {
1286 PrimitiveRefMut::Bool(b) => PrimitiveRef::Bool(b),
1287 PrimitiveRefMut::U8(n) => PrimitiveRef::U8(n),
1288 PrimitiveRefMut::U16(n) => PrimitiveRef::U16(n),
1289 PrimitiveRefMut::U32(n) => PrimitiveRef::U32(n),
1290 PrimitiveRefMut::U64(n) => PrimitiveRef::U64(n),
1291 PrimitiveRefMut::U128(n) => PrimitiveRef::U128(n),
1292 PrimitiveRefMut::I8(n) => PrimitiveRef::I8(n),
1293 PrimitiveRefMut::I16(n) => PrimitiveRef::I16(n),
1294 PrimitiveRefMut::I32(n) => PrimitiveRef::I32(n),
1295 PrimitiveRefMut::I64(n) => PrimitiveRef::I64(n),
1296 PrimitiveRefMut::I128(n) => PrimitiveRef::I128(n),
1297 PrimitiveRefMut::F32(n) => PrimitiveRef::F32(n),
1298 PrimitiveRefMut::F64(n) => PrimitiveRef::F64(n),
1299 PrimitiveRefMut::String(n) => PrimitiveRef::String(n),
1300 PrimitiveRefMut::Opaque {
1301 size,
1302 align,
1303 schema_ref,
1304 } => PrimitiveRef::Opaque {
1305 size: *size,
1306 align: *align,
1307 schema_ref: schema_ref.as_ref(),
1308 },
1309 }
1310 }
1311
1312 fn into_schema_ref_mut(self) -> SchemaRefMut<'ptr> {
1313 match self {
1314 PrimitiveRefMut::Bool(b) => SchemaRefMut::new(b),
1315 PrimitiveRefMut::U8(n) => SchemaRefMut::new(n),
1316 PrimitiveRefMut::U16(n) => SchemaRefMut::new(n),
1317 PrimitiveRefMut::U32(n) => SchemaRefMut::new(n),
1318 PrimitiveRefMut::U64(n) => SchemaRefMut::new(n),
1319 PrimitiveRefMut::U128(n) => SchemaRefMut::new(n),
1320 PrimitiveRefMut::I8(n) => SchemaRefMut::new(n),
1321 PrimitiveRefMut::I16(n) => SchemaRefMut::new(n),
1322 PrimitiveRefMut::I32(n) => SchemaRefMut::new(n),
1323 PrimitiveRefMut::I64(n) => SchemaRefMut::new(n),
1324 PrimitiveRefMut::I128(n) => SchemaRefMut::new(n),
1325 PrimitiveRefMut::F32(n) => SchemaRefMut::new(n),
1326 PrimitiveRefMut::F64(n) => SchemaRefMut::new(n),
1327 PrimitiveRefMut::String(s) => SchemaRefMut::new(s),
1328 PrimitiveRefMut::Opaque { schema_ref, .. } => schema_ref,
1329 }
1330 }
1331}
1332
1333impl<'a> From<SchemaRefMut<'a>> for PrimitiveRefMut<'a> {
1334 fn from(value: SchemaRefMut<'a>) -> Self {
1335 match &value.schema.kind {
1336 SchemaKind::Primitive(p) => match p {
1337 Primitive::Bool => PrimitiveRefMut::Bool(value.cast_into_mut()),
1338 Primitive::U8 => PrimitiveRefMut::U8(value.cast_into_mut()),
1339 Primitive::U16 => PrimitiveRefMut::U16(value.cast_into_mut()),
1340 Primitive::U32 => PrimitiveRefMut::U32(value.cast_into_mut()),
1341 Primitive::U64 => PrimitiveRefMut::U64(value.cast_into_mut()),
1342 Primitive::U128 => PrimitiveRefMut::U128(value.cast_into_mut()),
1343 Primitive::I8 => PrimitiveRefMut::I8(value.cast_into_mut()),
1344 Primitive::I16 => PrimitiveRefMut::I16(value.cast_into_mut()),
1345 Primitive::I32 => PrimitiveRefMut::I32(value.cast_into_mut()),
1346 Primitive::I64 => PrimitiveRefMut::I64(value.cast_into_mut()),
1347 Primitive::I128 => PrimitiveRefMut::I128(value.cast_into_mut()),
1348 Primitive::F32 => PrimitiveRefMut::F32(value.cast_into_mut()),
1349 Primitive::F64 => PrimitiveRefMut::F64(value.cast_into_mut()),
1350 Primitive::String => PrimitiveRefMut::String(value.cast_into_mut()),
1351 Primitive::Opaque { size, align } => PrimitiveRefMut::Opaque {
1352 size: *size,
1353 align: *align,
1354 schema_ref: value,
1355 },
1356 },
1357 _ => panic!("Schema mismatch"),
1358 }
1359 }
1360}
1361
1362pub struct SchemaBox {
1364 ptr: NonNull<c_void>,
1365 schema: &'static Schema,
1366}
1367impl Default for SchemaBox {
1368 fn default() -> Self {
1369 SchemaBox::new(())
1370 }
1371}
1372unsafe impl Sync for SchemaBox {}
1373unsafe impl Send for SchemaBox {}
1374impl std::fmt::Debug for SchemaBox {
1375 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1376 f.debug_struct("SchemaBox")
1377 .field("schema", &self.schema.full_name)
1378 .field("value", &SchemaRefValueDebug(self.as_ref()))
1379 .finish_non_exhaustive()
1380 }
1381}
1382impl std::fmt::Display for SchemaBox {
1383 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1384 self.as_ref().fmt(f)
1385 }
1386}
1387
1388impl Hash for SchemaBox {
1389 #[track_caller]
1390 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1391 let Some(hash_fn) = &self.schema.hash_fn else {
1392 panic!("Cannot hash schema box where schema doesn't provide hash_fn");
1393 };
1394 let hash = unsafe { (hash_fn.get())(self.ptr.as_ptr()) };
1395 state.write_u64(hash);
1396 }
1397}
1398
1399impl PartialEq for SchemaBox {
1400 fn eq(&self, other: &Self) -> bool {
1401 if self.schema != other.schema {
1402 panic!("Cannot compare two `SchemaBox`s with different schemas.");
1403 }
1404 let Some(eq_fn) = &self.schema.eq_fn else {
1405 panic!("Cannot hash schema box where schema doesn't provide hash_fn.");
1406 };
1407 unsafe { (eq_fn.get())(self.ptr.as_ptr(), other.ptr.as_ptr()) }
1408 }
1409}
1410impl Eq for SchemaBox {}
1411
1412impl Clone for SchemaBox {
1413 fn clone(&self) -> Self {
1414 let clone_fn = self.schema.clone_fn.as_ref().unwrap_or_else(|| {
1415 panic!(
1416 "The schema for this type does not allow cloning it.\nSchema: {:#?}",
1417 self.schema
1418 )
1419 });
1420
1421 let layout = self.schema.layout();
1422 let new_ptr = if layout.size() == 0 {
1423 NonNull::<c_void>::dangling().as_ptr()
1424 } else {
1425 unsafe { std::alloc::alloc(layout) as *mut c_void }
1427 };
1428 let new_ptr = unsafe {
1429 (clone_fn.get())(self.ptr.as_ptr(), new_ptr);
1430 NonNull::new(new_ptr).unwrap_or_else(|| handle_alloc_error(layout))
1431 };
1432 Self {
1433 ptr: new_ptr,
1434 schema: self.schema,
1435 }
1436 }
1437}
1438
1439impl SchemaBox {
1440 pub fn as_ptr(&self) -> *mut c_void {
1442 self.ptr.as_ptr()
1443 }
1444
1445 #[track_caller]
1449 pub fn cast_into<T: HasSchema>(self) -> T {
1450 self.try_cast_into().unwrap()
1451 }
1452
1453 pub fn try_cast_into<T: HasSchema>(self) -> Result<T, SchemaMismatchError> {
1457 if self.schema == T::schema() {
1458 Ok(unsafe { self.cast_into_unchecked() })
1460 } else {
1461 Err(SchemaMismatchError)
1462 }
1463 }
1464
1465 pub unsafe fn cast_into_unchecked<T: HasSchema>(self) -> T {
1469 let mut ret = MaybeUninit::<T>::uninit();
1471
1472 unsafe {
1475 (ret.as_mut_ptr() as *mut c_void)
1476 .copy_from_nonoverlapping(self.ptr.as_ptr(), self.schema.layout().size());
1477 }
1478
1479 self.forget();
1481
1482 unsafe { ret.assume_init() }
1484 }
1485
1486 #[track_caller]
1490 pub fn cast_ref<T: HasSchema>(&self) -> &T {
1491 self.try_cast_ref().expect(SchemaMismatchError::MSG)
1492 }
1493
1494 pub fn try_cast_ref<T: HasSchema>(&self) -> Result<&T, SchemaMismatchError> {
1498 if self.schema.represents(T::schema()) {
1499 unsafe { Ok(self.ptr.cast::<T>().as_ref()) }
1501 } else {
1502 Err(SchemaMismatchError)
1503 }
1504 }
1505
1506 #[track_caller]
1510 pub fn cast_mut<T: HasSchema>(&mut self) -> &mut T {
1511 self.try_cast_mut().expect(SchemaMismatchError::MSG)
1512 }
1513
1514 pub fn try_cast_mut<T: HasSchema>(&mut self) -> Result<&mut T, SchemaMismatchError> {
1518 if self.schema.represents(T::schema()) {
1519 unsafe { Ok(self.ptr.cast::<T>().as_mut()) }
1521 } else {
1522 Err(SchemaMismatchError)
1523 }
1524 }
1525
1526 pub fn as_ref(&self) -> SchemaRef<'_> {
1528 SchemaRef {
1529 ptr: self.ptr,
1530 schema: self.schema,
1531 _phantom: PhantomData,
1532 }
1533 }
1534
1535 pub fn as_mut(&mut self) -> SchemaRefMut<'_> {
1537 SchemaRefMut {
1538 ptr: self.ptr,
1539 schema: self.schema,
1540 _phantom: PhantomData,
1541 }
1542 }
1543
1544 #[track_caller]
1546 pub fn new<T: HasSchema + Sync + Send>(v: T) -> Self {
1547 let schema = T::schema();
1548 unsafe {
1550 let b = SchemaBox::uninitialized(schema);
1551 (b.ptr.as_ptr() as *mut T).write(v);
1552 b
1553 }
1554 }
1555
1556 pub unsafe fn uninitialized(schema: &'static Schema) -> Self {
1563 let layout = schema.layout();
1564
1565 let ptr = if layout.size() == 0 {
1566 NonNull::<c_void>::dangling().as_ptr()
1567 } else {
1568 std::alloc::alloc(layout) as *mut c_void
1570 };
1571 let ptr = NonNull::new(ptr).unwrap_or_else(|| handle_alloc_error(layout));
1573
1574 Self { ptr, schema }
1575 }
1576
1577 #[track_caller]
1584 pub fn default(schema: &'static Schema) -> Self {
1585 let Some(default_fn) = &schema.default_fn else {
1586 panic!("Schema doesn't have `default_fn` to create default value with.");
1587 };
1588
1589 unsafe {
1590 let b = SchemaBox::uninitialized(schema);
1591 (default_fn.get())(b.ptr.as_ptr());
1592 b
1593 }
1594 }
1595
1596 pub fn into_sbox<T: HasSchema>(self) -> SBox<T> {
1600 self.try_into_sbox()
1601 .unwrap_or_else(|_| panic!("{:?}", SchemaMismatchError))
1602 }
1603
1604 pub fn try_into_sbox<T: HasSchema>(self) -> Result<SBox<T>, Self> {
1608 if self.schema == T::schema() {
1609 Ok(SBox {
1610 b: self,
1611 _phantom: PhantomData,
1612 })
1613 } else {
1614 Err(self)
1615 }
1616 }
1617
1618 pub fn schema(&self) -> &'static Schema {
1620 self.schema
1621 }
1622
1623 pub unsafe fn from_raw_parts(ptr: NonNull<c_void>, schema: &'static Schema) -> Self {
1632 Self { ptr, schema }
1633 }
1634
1635 pub fn forget(mut self) {
1637 unsafe {
1638 self.dealloc();
1639 }
1640 std::mem::forget(self);
1641 }
1642
1643 pub fn try_hash(&self) -> Option<u64> {
1645 self.schema
1646 .hash_fn
1647 .as_ref()
1648 .map(|hash_fn| unsafe { (hash_fn.get())(self.ptr.as_ptr()) })
1649 }
1650
1651 #[track_caller]
1655 pub fn hash(&self) -> u64 {
1656 self.try_hash().expect("Schema doesn't implement hash")
1657 }
1658
1659 unsafe fn dealloc(&mut self) {
1661 if self.schema.layout().size() > 0 {
1662 std::alloc::dealloc(self.ptr.as_ptr() as *mut u8, self.schema.layout())
1663 }
1664 }
1665
1666 unsafe fn drop_inner(&mut self) {
1668 if let Some(drop_fn) = &self.schema.drop_fn {
1669 (drop_fn.get())(self.ptr.as_ptr());
1671 }
1672 }
1673}
1674
1675unsafe impl HasSchema for SchemaBox {
1676 fn schema() -> &'static Schema {
1677 use crate::raw_fns::*;
1678 use std::alloc::Layout;
1679 static S: OnceLock<&'static Schema> = OnceLock::new();
1680 let layout = Layout::new::<Self>();
1681 S.get_or_init(|| {
1682 SCHEMA_REGISTRY.register(SchemaData {
1683 name: type_name::<Self>().into(),
1684 full_name: format!("{}::{}", module_path!(), type_name::<Self>()).into(),
1685 kind: SchemaKind::Primitive(Primitive::Opaque {
1686 size: layout.size(),
1687 align: layout.align(),
1688 }),
1689 type_id: Some(TypeId::of::<Self>()),
1690 clone_fn: Some(<Self as RawClone>::raw_clone_cb()),
1691 drop_fn: Some(<Self as RawDrop>::raw_drop_cb()),
1692 default_fn: None,
1693 hash_fn: Some(<Self as RawHash>::raw_hash_cb()),
1694 eq_fn: Some(<Self as RawEq>::raw_eq_cb()),
1695 type_data: default(),
1696 })
1697 })
1698 }
1699}
1700
1701impl Drop for SchemaBox {
1702 fn drop(&mut self) {
1703 unsafe {
1704 self.drop_inner();
1705 self.dealloc();
1706 }
1707 }
1708}
1709
1710#[repr(transparent)]
1719pub struct SBox<T: HasSchema> {
1720 b: SchemaBox,
1721 _phantom: PhantomData<T>,
1722}
1723impl<T: HasSchema> Default for SBox<T> {
1724 #[track_caller]
1725 fn default() -> Self {
1726 let schema = T::schema();
1727 let Some(default_fn) = &schema.default_fn else {
1728 panic!("Schema doesn't implement default");
1729 };
1730 Self {
1731 b: unsafe {
1734 let mut b = SchemaBox::uninitialized(schema);
1735 (default_fn.get())(b.as_mut().as_ptr());
1736 b
1737 },
1738 _phantom: Default::default(),
1739 }
1740 }
1741}
1742impl<T: HasSchema> Clone for SBox<T> {
1743 fn clone(&self) -> Self {
1744 Self {
1745 b: self.b.clone(),
1746 _phantom: self._phantom,
1747 }
1748 }
1749}
1750impl<T: HasSchema + std::fmt::Debug> std::fmt::Debug for SBox<T> {
1751 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1752 f.debug_struct("SBox").field("b", &self.b).finish()
1753 }
1754}
1755unsafe impl<T: HasSchema> HasSchema for SBox<T> {
1756 fn schema() -> &'static Schema {
1757 static S: OnceLock<RwLock<HashMap<TypeId, &'static Schema>>> = OnceLock::new();
1758 let schema = {
1759 S.get_or_init(default)
1760 .read()
1761 .get(&TypeId::of::<Self>())
1762 .copied()
1763 };
1764 schema.unwrap_or_else(|| {
1765 let schema = SCHEMA_REGISTRY.register(SchemaData {
1766 name: type_name::<Self>().into(),
1767 full_name: format!("{}::{}", module_path!(), type_name::<Self>()).into(),
1768 kind: SchemaKind::Box(T::schema()),
1769 type_id: Some(TypeId::of::<Self>()),
1770 clone_fn: Some(<Self as RawClone>::raw_clone_cb()),
1771 drop_fn: Some(<Self as RawDrop>::raw_drop_cb()),
1772 default_fn: Some(<Self as RawDefault>::raw_default_cb()),
1773 hash_fn: Some(unsafe {
1774 Unsafe::new(Box::leak(Box::new(|a| SchemaVec::raw_hash(a))))
1775 }),
1776 eq_fn: Some(unsafe {
1777 Unsafe::new(Box::leak(Box::new(|a, b| SchemaVec::raw_eq(a, b))))
1778 }),
1779 type_data: Default::default(),
1780 });
1781
1782 S.get_or_init(default)
1783 .write()
1784 .insert(TypeId::of::<Self>(), schema);
1785
1786 schema
1787 })
1788 }
1789}
1790
1791impl<T: HasSchema> SBox<T> {
1792 pub fn new(value: T) -> Self {
1794 SBox {
1795 b: SchemaBox::new(value),
1796 _phantom: PhantomData,
1797 }
1798 }
1799
1800 pub fn into_schema_box(self) -> SchemaBox {
1802 self.b
1803 }
1804}
1805
1806impl<T: HasSchema> From<SBox<T>> for SchemaBox {
1807 fn from(value: SBox<T>) -> Self {
1808 value.b
1809 }
1810}
1811
1812impl<T: HasSchema> TryFrom<SchemaBox> for SBox<T> {
1813 type Error = SchemaBox;
1814 fn try_from(value: SchemaBox) -> Result<Self, Self::Error> {
1815 value.try_into_sbox()
1816 }
1817}
1818
1819impl<T: HasSchema> std::ops::Deref for SBox<T> {
1820 type Target = T;
1821
1822 fn deref(&self) -> &Self::Target {
1823 unsafe { self.b.ptr.cast::<T>().as_ref() }
1825 }
1826}
1827impl<T: HasSchema> std::ops::DerefMut for SBox<T> {
1828 fn deref_mut(&mut self) -> &mut Self::Target {
1829 unsafe { self.b.ptr.cast::<T>().as_mut() }
1831 }
1832}
1833
1834#[derive(Debug, Clone, Copy)]
1836pub enum FieldIdx<'a> {
1837 Name(&'a str),
1839 Idx(usize),
1841}
1842impl From<usize> for FieldIdx<'static> {
1843 fn from(value: usize) -> Self {
1844 Self::Idx(value)
1845 }
1846}
1847impl<'a> From<&'a str> for FieldIdx<'a> {
1848 fn from(value: &'a str) -> Self {
1849 Self::Name(value)
1850 }
1851}
1852impl<'a> From<&'a String> for FieldIdx<'a> {
1853 fn from(value: &'a String) -> Self {
1854 Self::Name(value)
1855 }
1856}
1857impl<'a> std::fmt::Display for FieldIdx<'a> {
1858 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1859 match self {
1860 Self::Idx(i) => write!(f, "{i}"),
1861 Self::Name(n) => write!(f, "{n}"),
1862 }
1863 }
1864}
1865
1866pub struct FieldPath<T>(pub T);
1869impl<'a> IntoIterator for FieldPath<&'a str> {
1870 type Item = FieldIdx<'a>;
1871 type IntoIter = Map<Filter<Split<'a, char>, fn(&&str) -> bool>, fn(&str) -> FieldIdx>;
1872
1873 fn into_iter(self) -> Self::IntoIter {
1874 fn flt(x: &&str) -> bool {
1875 !x.is_empty()
1876 }
1877 fn mp(x: &str) -> FieldIdx<'_> {
1878 x.parse::<usize>()
1879 .map(FieldIdx::Idx)
1880 .unwrap_or(FieldIdx::Name(x))
1881 }
1882 self.0.split('.').filter(flt as _).map(mp as _)
1883 }
1884}
1885impl IntoIterator for FieldPath<Ustr> {
1886 type Item = FieldIdx<'static>;
1887 type IntoIter = Map<Filter<Split<'static, char>, fn(&&str) -> bool>, fn(&str) -> FieldIdx>;
1888
1889 fn into_iter(self) -> Self::IntoIter {
1890 fn flt(x: &&str) -> bool {
1891 !x.is_empty()
1892 }
1893 fn mp(x: &str) -> FieldIdx<'_> {
1894 x.parse::<usize>()
1895 .map(FieldIdx::Idx)
1896 .unwrap_or(FieldIdx::Name(x))
1897 }
1898 self.0.as_str().split('.').filter(flt as _).map(mp as _)
1899 }
1900}
1901
1902#[derive(Debug)]
1904pub struct SchemaMismatchError;
1905impl SchemaMismatchError {
1906 pub const MSG: &'static str =
1908 "Invalid cast: the schemas of the casted types are not compatible.";
1909}
1910impl std::error::Error for SchemaMismatchError {}
1911impl std::fmt::Display for SchemaMismatchError {
1912 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1913 write!(f, "{}", Self::MSG)
1914 }
1915}
1916
1917#[derive(Debug)]
1919pub struct SchemaFieldNotFoundError<'a> {
1920 idx: FieldIdx<'a>,
1921}
1922impl<'a> std::error::Error for SchemaFieldNotFoundError<'a> {}
1923impl<'a> std::fmt::Display for SchemaFieldNotFoundError<'a> {
1924 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1925 write!(f, "Field not found in schema: {}", self.idx)
1926 }
1927}