| 261 | // Bootstrap decoder: writes tag to `*out_tag`, bytes to `dst[..dst_max]`. |
| 262 | #[unsafe(no_mangle)] |
| 263 | pub unsafe extern "C" fn host_edge_decode(h: u32, out_tag: *mut u32, dst: *mut u8, dst_max: u32) -> i32 { |
| 264 | let copy_into = |tag: u32, bytes: &[u8]| -> i32 { |
| 265 | unsafe { *out_tag = tag; } |
| 266 | if bytes.len() > dst_max as usize { return -(bytes.len() as i32); } |
| 267 | if !bytes.is_empty() { |
| 268 | unsafe { |
| 269 | core::ptr::copy_nonoverlapping(bytes.as_ptr(), dst, bytes.len()); |
| 270 | } |
| 271 | } |
| 272 | bytes.len() as i32 |
| 273 | }; |
| 274 | |
| 275 | let v = match get_val(h) { |
| 276 | Some(v) => v, |
| 277 | None => { unsafe { *out_tag = TAG_INVALID; } return 0; } |
| 278 | }; |
| 279 | |
| 280 | match classify_decode(v.0) { |
| 281 | DecodeBits::Primitive { tag, bytes } => match bytes { |
| 282 | PrimitiveBytes::None => copy_into(tag, &[]), |
| 283 | PrimitiveBytes::Bool(b) => copy_into(tag, &[b]), |
| 284 | PrimitiveBytes::Eight(a) => copy_into(tag, &a), |
| 285 | PrimitiveBytes::Sixteen(a) => copy_into(tag, &a), |
| 286 | }, |
| 287 | DecodeBits::Heap => { |
| 288 | // Str, Bytes and LongInt decode to primitives; other composites must go through `edge_op`. |
| 289 | enum Decoded { Str(alloc::string::String), Bytes(Vec<u8>), LongInt(i128), Other } |
| 290 | let decoded = with_vm(|vm| match vm.heap.get(v) { |
| 291 | HeapObj::Str(s) => Decoded::Str(s.clone()), |
| 292 | HeapObj::Bytes(b) => Decoded::Bytes(b.clone()), |
| 293 | HeapObj::LongInt(i) => Decoded::LongInt(*i), |
| 294 | _ => Decoded::Other, |
| 295 | }).unwrap_or(Decoded::Other); |
| 296 | match decoded { |
| 297 | Decoded::Str(s) => copy_into(crate::abi::Tag::Bytes as u32, s.as_bytes()), |
| 298 | Decoded::Bytes(b) => copy_into(crate::abi::Tag::Raw as u32, &b), |
| 299 | Decoded::LongInt(i) => copy_into(crate::abi::Tag::Int as u32, &i.to_le_bytes()), |
| 300 | Decoded::Other => { unsafe { *out_tag = TAG_INVALID; } 0 } |
| 301 | } |
| 302 | } |
| 303 | DecodeBits::Invalid => { unsafe { *out_tag = TAG_INVALID; } 0 } |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | // Decrement refcount on a handle. No-op for invalid handles. |
| 308 | #[unsafe(no_mangle)] |