Skip to main content

rib/
value.rs

1#[derive(Debug, Clone, PartialEq)]
2pub enum Value {
3    Bool(bool),
4    U8(u8),
5    U16(u16),
6    U32(u32),
7    U64(u64),
8    S8(i8),
9    S16(i16),
10    S32(i32),
11    S64(i64),
12    F32(f32),
13    F64(f64),
14    Char(char),
15    String(String),
16    List(Vec<Value>),
17    Tuple(Vec<Value>),
18    Record(Vec<Value>),
19    Variant {
20        case_idx: u32,
21        case_value: Option<Box<Value>>,
22    },
23    Enum(u32),
24    Flags(Vec<bool>),
25    Option(Option<Box<Value>>),
26    Result(Result<Option<Box<Value>>, Option<Box<Value>>>),
27    /// Guest resource handle at the interpreter boundary.
28    ///
29    /// - `resource_id` — embedder-defined id (for example a table slot in Wasmtime).
30    /// - `instance_name` — component **instance** key (`instance()` / `instance("x")`) used to route
31    ///   host calls for resource methods. When empty, [`handle_instance_name`](Value::handle_instance_name)
32    ///   falls back to the last `/` segment of `uri` for older embedders.
33    Handle {
34        uri: String,
35        resource_id: u64,
36        instance_name: String,
37    },
38}
39
40impl Value {
41    /// Instance key for routing resource method invocations to the correct host-side component
42    /// instance. Prefers [`Handle::instance_name`]; if empty, uses the last `/`-separated segment of
43    /// [`Handle::uri`].
44    pub fn handle_instance_name(&self) -> Option<String> {
45        match self {
46            Value::Handle {
47                uri,
48                instance_name,
49                resource_id: _,
50            } => {
51                if !instance_name.is_empty() {
52                    Some(instance_name.clone())
53                } else {
54                    Some(
55                        uri.rsplit_once('/')
56                            .map(|(_, last)| last.to_string())
57                            .unwrap_or_else(|| uri.clone()),
58                    )
59                }
60            }
61            _ => None,
62        }
63    }
64}
65
66impl std::fmt::Display for Value {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        match self {
69            Value::Bool(v) => write!(f, "{v}"),
70            Value::U8(v) => write!(f, "{v}"),
71            Value::U16(v) => write!(f, "{v}"),
72            Value::U32(v) => write!(f, "{v}"),
73            Value::U64(v) => write!(f, "{v}"),
74            Value::S8(v) => write!(f, "{v}"),
75            Value::S16(v) => write!(f, "{v}"),
76            Value::S32(v) => write!(f, "{v}"),
77            Value::S64(v) => write!(f, "{v}"),
78            Value::F32(v) => write!(f, "{v}"),
79            Value::F64(v) => write!(f, "{v}"),
80            Value::Char(v) => write!(f, "'{v}'"),
81            Value::String(v) => write!(f, "\"{v}\""),
82            Value::List(values) => {
83                write!(f, "[")?;
84                for (i, v) in values.iter().enumerate() {
85                    if i > 0 {
86                        write!(f, ", ")?;
87                    }
88                    write!(f, "{v}")?;
89                }
90                write!(f, "]")
91            }
92            Value::Tuple(values) => {
93                write!(f, "(")?;
94                for (i, v) in values.iter().enumerate() {
95                    if i > 0 {
96                        write!(f, ", ")?;
97                    }
98                    write!(f, "{v}")?;
99                }
100                write!(f, ")")
101            }
102            Value::Record(values) => {
103                write!(f, "{{")?;
104                for (i, v) in values.iter().enumerate() {
105                    if i > 0 {
106                        write!(f, ", ")?;
107                    }
108                    write!(f, "{v}")?;
109                }
110                write!(f, "}}")
111            }
112            Value::Variant {
113                case_idx,
114                case_value,
115            } => {
116                write!(f, "variant#{case_idx}")?;
117                if let Some(v) = case_value {
118                    write!(f, "({v})")?;
119                }
120                Ok(())
121            }
122            Value::Enum(idx) => write!(f, "enum#{idx}"),
123            Value::Flags(flags) => {
124                write!(f, "{{")?;
125                let mut first = true;
126                for (i, set) in flags.iter().enumerate() {
127                    if *set {
128                        if !first {
129                            write!(f, ", ")?;
130                        }
131                        write!(f, "flag#{i}")?;
132                        first = false;
133                    }
134                }
135                write!(f, "}}")
136            }
137            Value::Option(None) => write!(f, "none"),
138            Value::Option(Some(v)) => write!(f, "some({v})"),
139            Value::Result(Ok(Some(v))) => write!(f, "ok({v})"),
140            Value::Result(Ok(None)) => write!(f, "ok"),
141            Value::Result(Err(Some(v))) => write!(f, "err({v})"),
142            Value::Result(Err(None)) => write!(f, "err"),
143            Value::Handle {
144                uri,
145                resource_id,
146                instance_name,
147            } => write!(f, "handle({uri}#{resource_id} @ {instance_name})",),
148        }
149    }
150}