1#[cfg(feature = "alloc")]
12use alloc::alloc::{Layout, alloc, dealloc};
13use core::fmt::{self, Debug, Formatter};
14use core::hash::{Hash, Hasher};
15
16use crate::value::{TypeTag, Value};
17
18#[repr(u8)]
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23#[non_exhaustive]
24pub enum OtherKind {
25 QName = 0,
27 Uuid = 1,
29 Char = 2,
31}
32
33#[repr(C, align(8))]
41struct QNameHeader {
42 kind: OtherKind,
44 _pad: [u8; 7],
46 namespace: Value,
48 local_name: Value,
50}
51
52#[repr(transparent)]
60pub struct VQName(pub(crate) Value);
61
62impl VQName {
63 const fn layout() -> Layout {
64 Layout::new::<QNameHeader>()
65 }
66
67 #[cfg(feature = "alloc")]
68 fn alloc() -> *mut QNameHeader {
69 unsafe { alloc(Self::layout()).cast::<QNameHeader>() }
70 }
71
72 #[cfg(feature = "alloc")]
73 fn dealloc(ptr: *mut QNameHeader) {
74 unsafe {
75 dealloc(ptr.cast::<u8>(), Self::layout());
76 }
77 }
78
79 fn header(&self) -> &QNameHeader {
80 unsafe { &*(self.0.heap_ptr() as *const QNameHeader) }
81 }
82
83 #[cfg(feature = "alloc")]
85 #[must_use]
86 pub fn new(namespace: impl Into<Value>, local_name: impl Into<Value>) -> Self {
87 unsafe {
88 let ptr = Self::alloc();
89 core::ptr::write(&raw mut (*ptr).kind, OtherKind::QName);
91 core::ptr::write(&raw mut (*ptr)._pad, [0; 7]);
92 core::ptr::write(&raw mut (*ptr).namespace, namespace.into());
93 core::ptr::write(&raw mut (*ptr).local_name, local_name.into());
94 VQName(Value::new_ptr(ptr.cast(), TypeTag::Other))
95 }
96 }
97
98 #[cfg(feature = "alloc")]
100 #[must_use]
101 pub fn new_local(local_name: impl Into<Value>) -> Self {
102 Self::new(Value::NULL, local_name)
103 }
104
105 #[must_use]
107 pub fn namespace(&self) -> Option<&Value> {
108 let ns = &self.header().namespace;
109 if ns.is_null() { None } else { Some(ns) }
110 }
111
112 #[must_use]
114 pub fn local_name(&self) -> &Value {
115 &self.header().local_name
116 }
117
118 #[must_use]
120 pub fn has_namespace(&self) -> bool {
121 !self.header().namespace.is_null()
122 }
123
124 pub(crate) fn clone_impl(&self) -> Value {
127 #[cfg(feature = "alloc")]
128 {
129 let h = self.header();
130 Self::new(h.namespace.clone(), h.local_name.clone()).0
131 }
132 #[cfg(not(feature = "alloc"))]
133 {
134 panic!("cannot clone VQName without alloc feature")
135 }
136 }
137
138 pub(crate) fn drop_impl(&mut self) {
139 #[cfg(feature = "alloc")]
140 unsafe {
141 let ptr = self.0.heap_ptr_mut() as *mut QNameHeader;
142 core::ptr::drop_in_place(&mut (*ptr).namespace);
144 core::ptr::drop_in_place(&mut (*ptr).local_name);
145 Self::dealloc(ptr);
146 }
147 }
148}
149
150impl Clone for VQName {
151 fn clone(&self) -> Self {
152 VQName(self.clone_impl())
153 }
154}
155
156impl PartialEq for VQName {
157 fn eq(&self, other: &Self) -> bool {
158 let (h1, h2) = (self.header(), other.header());
159 h1.namespace == h2.namespace && h1.local_name == h2.local_name
160 }
161}
162
163impl Eq for VQName {}
164
165impl Hash for VQName {
166 fn hash<H: Hasher>(&self, state: &mut H) {
167 let h = self.header();
168 h.namespace.hash(state);
169 h.local_name.hash(state);
170 }
171}
172
173impl Debug for VQName {
174 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
175 let h = self.header();
176 if h.namespace.is_null() {
177 write!(f, "{:?}", h.local_name)
178 } else {
179 write!(f, "{{{:?}}}{:?}", h.namespace, h.local_name)
180 }
181 }
182}
183
184#[cfg(feature = "alloc")]
185impl From<VQName> for Value {
186 fn from(qname: VQName) -> Self {
187 qname.0
188 }
189}
190
191#[repr(C, align(8))]
199struct UuidHeader {
200 kind: OtherKind,
202 _pad: [u8; 7],
204 bytes: [u8; 16],
206}
207
208#[repr(transparent)]
214pub struct VUuid(pub(crate) Value);
215
216impl VUuid {
217 const fn layout() -> Layout {
218 Layout::new::<UuidHeader>()
219 }
220
221 #[cfg(feature = "alloc")]
222 fn alloc() -> *mut UuidHeader {
223 unsafe { alloc(Self::layout()).cast::<UuidHeader>() }
224 }
225
226 #[cfg(feature = "alloc")]
227 fn dealloc(ptr: *mut UuidHeader) {
228 unsafe {
229 dealloc(ptr.cast::<u8>(), Self::layout());
230 }
231 }
232
233 fn header(&self) -> &UuidHeader {
234 unsafe { &*(self.0.heap_ptr() as *const UuidHeader) }
235 }
236
237 #[cfg(feature = "alloc")]
239 #[must_use]
240 pub fn new(bytes: [u8; 16]) -> Self {
241 unsafe {
242 let ptr = Self::alloc();
243 core::ptr::write(&raw mut (*ptr).kind, OtherKind::Uuid);
245 core::ptr::write(&raw mut (*ptr)._pad, [0; 7]);
246 core::ptr::write(&raw mut (*ptr).bytes, bytes);
247 VUuid(Value::new_ptr(ptr.cast(), TypeTag::Other))
248 }
249 }
250
251 #[cfg(feature = "alloc")]
253 #[must_use]
254 pub fn from_u64_pair(high: u64, low: u64) -> Self {
255 let mut bytes = [0u8; 16];
256 bytes[..8].copy_from_slice(&high.to_be_bytes());
257 bytes[8..].copy_from_slice(&low.to_be_bytes());
258 Self::new(bytes)
259 }
260
261 #[cfg(feature = "alloc")]
263 #[must_use]
264 pub fn from_u128(value: u128) -> Self {
265 Self::new(value.to_be_bytes())
266 }
267
268 #[must_use]
270 pub fn as_bytes(&self) -> &[u8; 16] {
271 &self.header().bytes
272 }
273
274 #[must_use]
276 pub fn as_u128(&self) -> u128 {
277 u128::from_be_bytes(self.header().bytes)
278 }
279
280 #[must_use]
282 pub fn high(&self) -> u64 {
283 let bytes = &self.header().bytes;
284 u64::from_be_bytes([
285 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
286 ])
287 }
288
289 #[must_use]
291 pub fn low(&self) -> u64 {
292 let bytes = &self.header().bytes;
293 u64::from_be_bytes([
294 bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
295 ])
296 }
297
298 pub(crate) fn clone_impl(&self) -> Value {
301 #[cfg(feature = "alloc")]
302 {
303 Self::new(self.header().bytes).0
304 }
305 #[cfg(not(feature = "alloc"))]
306 {
307 panic!("cannot clone VUuid without alloc feature")
308 }
309 }
310
311 pub(crate) fn drop_impl(&mut self) {
312 #[cfg(feature = "alloc")]
313 unsafe {
314 Self::dealloc(self.0.heap_ptr_mut().cast());
315 }
316 }
317}
318
319impl Clone for VUuid {
320 fn clone(&self) -> Self {
321 VUuid(self.clone_impl())
322 }
323}
324
325impl PartialEq for VUuid {
326 fn eq(&self, other: &Self) -> bool {
327 self.header().bytes == other.header().bytes
328 }
329}
330
331impl Eq for VUuid {}
332
333impl Hash for VUuid {
334 fn hash<H: Hasher>(&self, state: &mut H) {
335 self.header().bytes.hash(state);
336 }
337}
338
339impl Debug for VUuid {
340 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
341 let bytes = &self.header().bytes;
342 write!(
344 f,
345 "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
346 bytes[0],
347 bytes[1],
348 bytes[2],
349 bytes[3],
350 bytes[4],
351 bytes[5],
352 bytes[6],
353 bytes[7],
354 bytes[8],
355 bytes[9],
356 bytes[10],
357 bytes[11],
358 bytes[12],
359 bytes[13],
360 bytes[14],
361 bytes[15]
362 )
363 }
364}
365
366#[cfg(feature = "alloc")]
367impl From<VUuid> for Value {
368 fn from(uuid: VUuid) -> Self {
369 uuid.0
370 }
371}
372
373#[cfg(feature = "alloc")]
374impl From<[u8; 16]> for VUuid {
375 fn from(bytes: [u8; 16]) -> Self {
376 Self::new(bytes)
377 }
378}
379
380#[cfg(feature = "alloc")]
381impl From<u128> for VUuid {
382 fn from(value: u128) -> Self {
383 Self::from_u128(value)
384 }
385}
386
387#[repr(C, align(8))]
398struct CharHeader {
399 kind: OtherKind,
401 _pad: [u8; 3],
403 utf8_len: u8,
405 utf8: [u8; 4],
407 ch: u32,
409}
410
411#[repr(transparent)]
417pub struct VChar(pub(crate) Value);
418
419impl VChar {
420 const fn layout() -> Layout {
421 Layout::new::<CharHeader>()
422 }
423
424 #[cfg(feature = "alloc")]
425 fn alloc() -> *mut CharHeader {
426 unsafe { alloc(Self::layout()).cast::<CharHeader>() }
427 }
428
429 #[cfg(feature = "alloc")]
430 fn dealloc(ptr: *mut CharHeader) {
431 unsafe {
432 dealloc(ptr.cast::<u8>(), Self::layout());
433 }
434 }
435
436 fn header(&self) -> &CharHeader {
437 unsafe { &*(self.0.heap_ptr() as *const CharHeader) }
438 }
439
440 #[cfg(feature = "alloc")]
442 #[must_use]
443 pub fn new(c: char) -> Self {
444 let mut utf8 = [0u8; 4];
445 let utf8_len = c.encode_utf8(&mut utf8).len() as u8;
446 unsafe {
447 let ptr = Self::alloc();
448 core::ptr::write(&raw mut (*ptr).kind, OtherKind::Char);
450 core::ptr::write(&raw mut (*ptr)._pad, [0; 3]);
451 core::ptr::write(&raw mut (*ptr).utf8_len, utf8_len);
452 core::ptr::write(&raw mut (*ptr).utf8, utf8);
453 core::ptr::write(&raw mut (*ptr).ch, c as u32);
454 VChar(Value::new_ptr(ptr.cast(), TypeTag::Other))
455 }
456 }
457
458 #[must_use]
460 pub fn value(&self) -> char {
461 unsafe { char::from_u32_unchecked(self.header().ch) }
463 }
464
465 #[must_use]
467 pub fn as_str(&self) -> &str {
468 let h = self.header();
469 let bytes = &h.utf8[..h.utf8_len as usize];
470 unsafe { core::str::from_utf8_unchecked(bytes) }
472 }
473
474 pub(crate) fn clone_impl(&self) -> Value {
477 #[cfg(feature = "alloc")]
478 {
479 Self::new(self.value()).0
480 }
481 #[cfg(not(feature = "alloc"))]
482 {
483 panic!("cannot clone VChar without alloc feature")
484 }
485 }
486
487 pub(crate) fn drop_impl(&mut self) {
488 #[cfg(feature = "alloc")]
489 unsafe {
490 Self::dealloc(self.0.heap_ptr_mut().cast());
491 }
492 }
493}
494
495impl Clone for VChar {
496 fn clone(&self) -> Self {
497 VChar(self.clone_impl())
498 }
499}
500
501impl PartialEq for VChar {
502 fn eq(&self, other: &Self) -> bool {
503 self.header().ch == other.header().ch
504 }
505}
506
507impl Eq for VChar {}
508
509impl Hash for VChar {
510 fn hash<H: Hasher>(&self, state: &mut H) {
511 self.value().hash(state);
512 }
513}
514
515impl Debug for VChar {
516 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
517 Debug::fmt(&self.value(), f)
518 }
519}
520
521#[cfg(feature = "alloc")]
522impl From<char> for VChar {
523 fn from(c: char) -> Self {
524 Self::new(c)
525 }
526}
527
528#[cfg(feature = "alloc")]
529impl From<char> for Value {
530 fn from(c: char) -> Self {
531 VChar::new(c).0
532 }
533}
534
535#[cfg(feature = "alloc")]
536impl From<VChar> for Value {
537 fn from(c: VChar) -> Self {
538 c.0
539 }
540}
541
542pub(crate) unsafe fn get_other_kind(value: &Value) -> OtherKind {
551 let ptr = value.heap_ptr();
553 unsafe { *(ptr as *const OtherKind) }
554}
555
556#[cfg(test)]
557mod tests {
558 use super::*;
559 use crate::VString;
560
561 #[test]
562 fn test_qname_with_namespace() {
563 let qname = VQName::new(VString::new("http://example.com"), VString::new("element"));
564 assert!(qname.has_namespace());
565 assert_eq!(
566 qname.namespace().unwrap().as_string().unwrap().as_str(),
567 "http://example.com"
568 );
569 assert_eq!(qname.local_name().as_string().unwrap().as_str(), "element");
570 }
571
572 #[test]
573 fn test_qname_local_only() {
574 let qname = VQName::new_local(VString::new("element"));
575 assert!(!qname.has_namespace());
576 assert!(qname.namespace().is_none());
577 assert_eq!(qname.local_name().as_string().unwrap().as_str(), "element");
578 }
579
580 #[test]
581 fn test_qname_clone() {
582 let qname = VQName::new(VString::new("ns"), VString::new("local"));
583 let cloned = qname.clone();
584 assert_eq!(qname, cloned);
585 }
586
587 #[test]
588 fn test_qname_debug() {
589 let qname = VQName::new(VString::new("ns"), VString::new("local"));
590 let debug = format!("{qname:?}");
591 assert!(debug.contains("ns"));
592 assert!(debug.contains("local"));
593 }
594
595 #[test]
596 fn test_uuid_new() {
597 let bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
598 let uuid = VUuid::new(bytes);
599 assert_eq!(uuid.as_bytes(), &bytes);
600 }
601
602 #[test]
603 fn test_uuid_from_u128() {
604 let value: u128 = 0x0102030405060708090a0b0c0d0e0f10;
605 let uuid = VUuid::from_u128(value);
606 assert_eq!(uuid.as_u128(), value);
607 }
608
609 #[test]
610 fn test_uuid_high_low() {
611 let uuid = VUuid::from_u64_pair(0x0102030405060708, 0x090a0b0c0d0e0f10);
612 assert_eq!(uuid.high(), 0x0102030405060708);
613 assert_eq!(uuid.low(), 0x090a0b0c0d0e0f10);
614 }
615
616 #[test]
617 fn test_uuid_clone() {
618 let uuid = VUuid::from_u128(0x12345678_9abc_def0_1234_56789abcdef0);
619 let cloned = uuid.clone();
620 assert_eq!(uuid, cloned);
621 }
622
623 #[test]
624 fn test_uuid_debug_format() {
625 let uuid = VUuid::from_u128(0x12345678_9abc_def0_1234_56789abcdef0);
626 let debug = format!("{uuid:?}");
627 assert_eq!(debug, "12345678-9abc-def0-1234-56789abcdef0");
628 }
629
630 #[test]
631 fn test_char_value_and_str() {
632 let c = VChar::new('λ');
633 assert_eq!(c.value(), 'λ');
634 assert_eq!(c.as_str(), "λ");
635
636 let ascii = VChar::new('A');
637 assert_eq!(ascii.value(), 'A');
638 assert_eq!(ascii.as_str(), "A");
639
640 let emoji = VChar::new('\u{1F600}');
642 assert_eq!(emoji.value(), '\u{1F600}');
643 assert_eq!(emoji.as_str(), "\u{1F600}");
644 }
645
646 #[test]
647 fn test_char_clone_eq() {
648 let c = VChar::new('λ');
649 let cloned = c.clone();
650 assert_eq!(c, cloned);
651 assert_ne!(c, VChar::new('μ'));
652 }
653
654 #[test]
655 fn test_char_debug() {
656 let c = VChar::new('x');
657 assert_eq!(format!("{c:?}"), "'x'");
658 }
659}