use core::{fmt, mem};
use facet_core::{
Def, Facet, FieldBuilder, Shape, StructKind, TypeOpsDirect, type_ops_direct, vtable_direct,
};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Span {
pub offset: u32,
pub len: u32,
}
impl fmt::Display for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[{}..{})", self.offset, self.offset + self.len)
}
}
impl Span {
pub const fn new(offset: usize, len: usize) -> Self {
Self {
offset: if offset > u32::MAX as usize {
u32::MAX
} else {
offset as u32
},
len: if len > u32::MAX as usize {
u32::MAX
} else {
len as u32
},
}
}
pub const fn is_unknown(&self) -> bool {
self.offset == 0 && self.len == 0
}
pub const fn end(&self) -> usize {
self.offset as usize + self.len as usize
}
}
unsafe impl Facet<'_> for Span {
const SHAPE: &'static Shape = &const {
static FIELDS: [facet_core::Field; 2] = [
FieldBuilder::new(
"offset",
facet_core::shape_of::<u32>,
mem::offset_of!(Span, offset),
)
.build(),
FieldBuilder::new(
"len",
facet_core::shape_of::<u32>,
mem::offset_of!(Span, len),
)
.build(),
];
const VTABLE: facet_core::VTableDirect = vtable_direct!(Span => Debug, PartialEq);
const TYPE_OPS: TypeOpsDirect = type_ops_direct!(Span => Default, Clone);
Shape::builder_for_sized::<Span>("Span")
.vtable_direct(&VTABLE)
.type_ops_direct(&TYPE_OPS)
.ty(facet_core::Type::struct_builder(StructKind::Struct, &FIELDS).build())
.def(Def::Undefined)
.build()
};
}
pub fn get_metadata_container_value_shape(shape: &Shape) -> Option<&'static Shape> {
use facet_core::{Type, UserType};
if !shape.is_metadata_container() {
return None;
}
if let Type::User(UserType::Struct(struct_def)) = &shape.ty {
struct_def
.fields
.iter()
.find(|f| !f.is_metadata())
.map(|f| f.shape.get())
} else {
None
}
}