hyperlight_common/component.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 The Hyperlight Authors.
3
4//! Support types for the bindings that `host_bindgen!` generates.
5
6use crate::resource::BorrowedResourceGuard;
7
8mod private {
9 pub trait Sealed {}
10}
11
12/// Whether an instance/resource/etc is being used in a positive or
13/// negative position in the top-level component type that governs the
14/// interface. That is to say, whether the functions provided by this
15/// instance/resource (or exported by this component) are expected to
16/// be implemented in the guest and called on the host or vice versa.
17///
18/// We say that a piece of a top-level component type is in "negative
19/// position" if it is on the left hand side of an odd number of
20/// arrows, and positive otherwise. With only first-order component
21/// types, this distinction collapses to whether it is part of an
22/// import (negative) or export (positive), but with higher-order
23/// components, this is no longer the case. For example, if a
24/// component imports another component which itself imports some
25/// functions, those functions are in positive position in the overall
26/// type---because they are supplied by the guest when it instantiates
27/// the component it imported---even though they are syntactically
28/// imports.
29pub trait Positivity: private::Sealed {
30 type NegativeOfThis: Positivity<NegativeOfThis = Self>;
31 /// How a call to one of the interface's functions returns.
32 type CallResult<T>;
33 /// How a borrowed resource handle reaches the implementation.
34 type Borrow<'a, T: 'a>;
35}
36
37/// A type is being used in a negative position in the overall type:
38/// it is implemented by the host, and the guest calls it.
39pub enum Negative {}
40
41/// A type is being used in a positive position in the overall type:
42/// it is implemented by the guest, and the host calls it.
43pub enum Positive {}
44
45impl private::Sealed for Negative {}
46impl private::Sealed for Positive {}
47
48impl Positivity for Negative {
49 type NegativeOfThis = Positive;
50 /// A host implementation is called directly, so it cannot fail.
51 type CallResult<T> = T;
52 /// A handle arrives as an index into the resource table, held borrowed
53 /// for the duration of the call.
54 type Borrow<'a, T: 'a> = BorrowedResourceGuard<'a, T>;
55}
56
57impl Positivity for Positive {
58 type NegativeOfThis = Negative;
59 /// Every call from the host crosses into the VM, where the guest can trap.
60 #[cfg(feature = "std")]
61 type CallResult<T> = anyhow::Result<T>;
62 /// The guest is not permitted to semantically enlarge its
63 /// functions to include kinds of failures other than the usual
64 /// trap/VM issue
65 #[cfg(not(feature = "std"))]
66 type CallResult<T> = T;
67 /// The host owns the value, so it hands out a plain reference.
68 type Borrow<'a, T: 'a> = &'a T;
69}