1use core::{mem, ops::Deref};
4
5use facet_core::{
6 Def, Facet, FieldBuilder, Shape, StructKind, TypeOpsDirect, type_ops_direct, vtable_direct,
7};
8
9#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
14pub struct Span {
15 pub offset: usize,
17 pub len: usize,
19}
20
21impl Span {
22 pub const fn new(offset: usize, len: usize) -> Self {
24 Self { offset, len }
25 }
26
27 pub fn is_unknown(&self) -> bool {
29 self.offset == 0 && self.len == 0
30 }
31
32 pub fn end(&self) -> usize {
34 self.offset + self.len
35 }
36}
37
38#[cfg(feature = "miette")]
39impl From<Span> for miette::SourceSpan {
40 fn from(span: Span) -> Self {
41 miette::SourceSpan::new(span.offset.into(), span.len)
42 }
43}
44
45#[cfg(feature = "miette")]
46impl From<miette::SourceSpan> for Span {
47 fn from(span: miette::SourceSpan) -> Self {
48 Self {
49 offset: span.offset(),
50 len: span.len(),
51 }
52 }
53}
54
55unsafe impl Facet<'_> for Span {
57 const SHAPE: &'static Shape = &const {
58 static FIELDS: [facet_core::Field; 2] = [
59 FieldBuilder::new(
60 "offset",
61 facet_core::shape_of::<usize>,
62 mem::offset_of!(Span, offset),
63 )
64 .build(),
65 FieldBuilder::new(
66 "len",
67 facet_core::shape_of::<usize>,
68 mem::offset_of!(Span, len),
69 )
70 .build(),
71 ];
72
73 const VTABLE: facet_core::VTableDirect = vtable_direct!(Span => Debug, PartialEq);
74 const TYPE_OPS: TypeOpsDirect = type_ops_direct!(Span => Default, Clone);
75
76 Shape::builder_for_sized::<Span>("Span")
77 .vtable_direct(&VTABLE)
78 .type_ops_direct(&TYPE_OPS)
79 .ty(facet_core::Type::struct_builder(StructKind::Struct, &FIELDS).build())
80 .def(Def::Undefined)
81 .build()
82 };
83}
84
85#[derive(Debug)]
91pub struct Spanned<T> {
92 pub value: T,
94 pub span: Span,
96}
97
98impl<T> Spanned<T> {
99 pub const fn new(value: T, span: Span) -> Self {
101 Self { value, span }
102 }
103
104 pub fn span(&self) -> Span {
106 self.span
107 }
108
109 pub fn value(&self) -> &T {
111 &self.value
112 }
113
114 pub fn into_inner(self) -> T {
116 self.value
117 }
118}
119
120impl<T> Deref for Spanned<T> {
121 type Target = T;
122 fn deref(&self) -> &Self::Target {
123 &self.value
124 }
125}
126
127impl<T: Default> Default for Spanned<T> {
128 fn default() -> Self {
129 Self {
130 value: T::default(),
131 span: Span::default(),
132 }
133 }
134}
135
136impl<T: Clone> Clone for Spanned<T> {
137 fn clone(&self) -> Self {
138 Self {
139 value: self.value.clone(),
140 span: self.span,
141 }
142 }
143}
144
145impl<T: PartialEq> PartialEq for Spanned<T> {
146 fn eq(&self, other: &Self) -> bool {
147 self.value == other.value
149 }
150}
151
152impl<T: Eq> Eq for Spanned<T> {}
153
154unsafe impl<'a, T: Facet<'a>> Facet<'a> for Spanned<T> {
156 const SHAPE: &'static Shape = &const {
157 use facet_core::{TypeOpsIndirect, TypeParam, VTableIndirect};
158
159 unsafe fn drop_in_place<T>(ox: facet_core::OxPtrMut) {
160 unsafe { core::ptr::drop_in_place(ox.ptr().as_byte_ptr() as *mut Spanned<T>) };
162 }
163
164 Shape::builder_for_sized::<Spanned<T>>("Spanned")
165 .vtable_indirect(&VTableIndirect::EMPTY)
166 .type_ops_indirect(
167 &const {
168 TypeOpsIndirect {
169 drop_in_place: drop_in_place::<T>,
170 default_in_place: None,
171 clone_into: None,
172 is_truthy: None,
173 }
174 },
175 )
176 .type_params(
177 &const {
178 [TypeParam {
179 name: "T",
180 shape: T::SHAPE,
181 }]
182 },
183 )
184 .ty(facet_core::Type::struct_builder(
185 StructKind::Struct,
186 &const {
187 [
188 FieldBuilder::new(
189 "value",
190 facet_core::shape_of::<T>,
191 mem::offset_of!(Spanned<T>, value),
192 )
193 .build(),
194 FieldBuilder::new(
195 "span",
196 facet_core::shape_of::<Span>,
197 mem::offset_of!(Spanned<T>, span),
198 )
199 .metadata("span")
202 .build(),
203 ]
204 },
205 )
206 .build())
207 .def(Def::Undefined)
208 .type_name(|_shape, f, opts| {
209 write!(f, "Spanned")?;
210 if let Some(opts) = opts.for_children() {
211 write!(f, "<")?;
212 if let Some(type_name_fn) = T::SHAPE.type_name {
213 type_name_fn(T::SHAPE, f, opts)?;
214 } else {
215 write!(f, "{}", T::SHAPE.type_identifier)?;
216 }
217 write!(f, ">")?;
218 } else {
219 write!(f, "<…>")?;
220 }
221 Ok(())
222 })
223 .build()
224 };
225}
226
227pub fn is_spanned_shape(shape: &Shape) -> bool {
236 use facet_core::{Type, UserType};
237
238 if let Type::User(UserType::Struct(struct_def)) = &shape.ty {
239 let has_span_metadata = struct_def
240 .fields
241 .iter()
242 .any(|f| f.metadata_kind() == Some("span"));
243 let has_value_field = struct_def.fields.iter().any(|f| !f.is_metadata());
244 return has_span_metadata && has_value_field;
245 }
246 false
247}
248
249pub fn find_span_metadata_field(shape: &Shape) -> Option<&'static facet_core::Field> {
253 use facet_core::{Type, UserType};
254
255 if let Type::User(UserType::Struct(struct_def)) = &shape.ty {
256 return struct_def
257 .fields
258 .iter()
259 .find(|f| f.metadata_kind() == Some("span"));
260 }
261 None
262}
263
264pub fn get_spanned_inner_shape(shape: &Shape) -> Option<&'static Shape> {
275 use facet_core::{Type, UserType};
276
277 if !is_spanned_shape(shape) {
278 return None;
279 }
280
281 if let Type::User(UserType::Struct(struct_def)) = &shape.ty {
282 struct_def
284 .fields
285 .iter()
286 .find(|f| !f.is_metadata())
287 .map(|f| f.shape.get())
288 } else {
289 None
290 }
291}