1use core::cell::Cell;
4use core::fmt;
5use core::num::NonZeroUsize;
6
7use crate as rune;
8use crate::alloc::borrow::Cow;
9use crate::alloc::prelude::*;
10use rust_alloc::rc::Rc;
11
12#[cfg(feature = "musli")]
13use musli::{Decode, Encode};
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, TryClone)]
19pub(crate) struct Label {
20 pub(crate) name: &'static str,
21 pub(crate) index: usize,
22 #[try_clone(with = Rc::clone)]
23 jump: Rc<Cell<Option<NonZeroUsize>>>,
24}
25
26impl Label {
27 #[inline]
29 pub(crate) fn new(name: &'static str, index: usize) -> Self {
30 Self {
31 name,
32 index,
33 jump: Rc::new(Cell::new(None)),
34 }
35 }
36
37 #[inline]
39 pub(crate) fn jump(&self) -> Option<usize> {
40 Some(self.jump.get()?.get().wrapping_sub(1))
41 }
42
43 #[inline]
45 pub(crate) fn set_jump(&self, jump: usize) -> bool {
46 let Some(jump) = NonZeroUsize::new(jump.wrapping_add(1)) else {
47 return false;
48 };
49
50 self.jump.replace(Some(jump));
51 true
52 }
53
54 #[inline]
56 pub(crate) fn to_debug_label(&self) -> DebugLabel {
57 DebugLabel {
58 name: self.name.into(),
59 index: self.index,
60 jump: self.jump.get(),
61 }
62 }
63}
64
65impl fmt::Display for Label {
66 #[inline]
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 if let Some(jump) = self.jump() {
69 write!(f, "{}_{} ({jump})", self.name, self.index)
70 } else {
71 write!(f, "{}_{}", self.name, self.index)
72 }
73 }
74}
75
76#[derive(Debug, TryClone, PartialEq, Eq, Hash)]
78#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
79#[cfg_attr(feature = "musli", derive(Encode, Decode))]
80pub struct DebugLabel {
81 name: Cow<'static, str>,
83 index: usize,
85 jump: Option<NonZeroUsize>,
87}
88
89impl DebugLabel {
90 #[inline]
92 pub(crate) fn jump(&self) -> Option<usize> {
93 Some(self.jump?.get().wrapping_sub(1))
94 }
95}
96
97impl fmt::Display for DebugLabel {
98 #[inline]
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 write!(f, "{}_{}", self.name, self.index)?;
101
102 if let Some(jump) = self.jump() {
103 write!(f, " ({jump})")?;
104 }
105
106 Ok(())
107 }
108}