rune/runtime/
label.rs

1//! A simple label used to jump to a code location.
2
3use 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
12use serde::{Deserialize, Serialize};
13
14/// A label that can be jumped to.
15#[derive(Debug, TryClone)]
16pub(crate) struct Label {
17    pub(crate) name: &'static str,
18    pub(crate) index: usize,
19    #[try_clone(with = Rc::clone)]
20    jump: Rc<Cell<Option<NonZeroUsize>>>,
21}
22
23impl Label {
24    /// Construct a new label.
25    pub(crate) fn new(name: &'static str, index: usize) -> Self {
26        Self {
27            name,
28            index,
29            jump: Rc::new(Cell::new(None)),
30        }
31    }
32
33    /// Get jump.
34    pub(crate) fn jump(&self) -> Option<usize> {
35        Some(self.jump.get()?.get().wrapping_sub(1))
36    }
37
38    /// Set jump.
39    pub(crate) fn set_jump(&self, jump: usize) -> bool {
40        let Some(jump) = NonZeroUsize::new(jump.wrapping_add(1)) else {
41            return false;
42        };
43
44        self.jump.replace(Some(jump));
45        true
46    }
47
48    /// Convert into owned label.
49    pub(crate) fn to_debug_label(&self) -> DebugLabel {
50        DebugLabel {
51            name: self.name.into(),
52            index: self.index,
53            jump: self.jump.get(),
54        }
55    }
56}
57
58impl fmt::Display for Label {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        if let Some(jump) = self.jump() {
61            write!(f, "{}_{} ({jump})", self.name, self.index)
62        } else {
63            write!(f, "{}_{}", self.name, self.index)
64        }
65    }
66}
67
68/// A label that can be jumped to.
69#[derive(Debug, TryClone, PartialEq, Eq, Hash, Serialize, Deserialize)]
70pub struct DebugLabel {
71    /// The name of the label.
72    name: Cow<'static, str>,
73    /// The index of the label.
74    index: usize,
75    /// The jump index of the label.
76    jump: Option<NonZeroUsize>,
77}
78
79impl DebugLabel {
80    /// Get jump.
81    pub(crate) fn jump(&self) -> Option<usize> {
82        Some(self.jump?.get().wrapping_sub(1))
83    }
84}
85
86impl fmt::Display for DebugLabel {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        write!(f, "{}_{}", self.name, self.index)?;
89
90        if let Some(jump) = self.jump() {
91            write!(f, " ({jump})")?;
92        }
93
94        Ok(())
95    }
96}