Skip to content

Commit 2b1dbc6

Browse files
committed
Add documentation to spin-core crate
Signed-off-by: Lann Martin <lann.martin@fermyon.com>
1 parent 4024e09 commit 2b1dbc6

File tree

4 files changed

+144
-6
lines changed

4 files changed

+144
-6
lines changed

crates/core/src/host_component.rs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,56 @@ use anyhow::Result;
44

55
use super::{Data, Linker};
66

7+
/// A trait for Spin "host components".
8+
///
9+
/// A Spin host component is an interface provided to Spin components that is
10+
/// implemented by the host. This trait is designed to be compatible with
11+
/// [`wit-bindgen`](https://github.com/bytecodealliance/wit-bindgen)'s
12+
/// generated bindings.
13+
///
14+
/// # Example
15+
///
16+
/// ```ignore
17+
/// wit_bindgen_wasmtime::export!({paths: ["my-interface.wit"], async: *});
18+
///
19+
/// #[derive(Default)]
20+
/// struct MyHostComponent {
21+
/// // ...
22+
/// }
23+
///
24+
/// #[async_trait]
25+
/// impl my_interface::MyInterface for MyHostComponent {
26+
/// // ...
27+
/// }
28+
///
29+
/// impl HostComponent for MyHostComponent {
30+
/// type Data = Self;
31+
///
32+
/// fn add_to_linker<T: Send>(
33+
/// linker: &mut Linker<T>,
34+
/// get: impl Fn(&mut spin_core::Data<T>) -> &mut Self::Data + Send + Sync + Copy + 'static,
35+
/// ) -> anyhow::Result<()> {
36+
/// my_interface::add_to_linker(linker, get)
37+
/// }
38+
///
39+
/// fn build_data(&self) -> Self::Data {
40+
/// Default::default()
41+
/// }
42+
/// }
43+
/// ```
744
pub trait HostComponent: Send + Sync + 'static {
845
/// Host component runtime data.
946
type Data: Send + Sized + 'static;
1047

1148
/// Add this component to the given Linker, using the given runtime state-getting handle.
12-
// This function signature mirrors those generated by wit-bindgen.
49+
///
50+
/// This function signature mirrors those generated by `wit-bindgen`.
1351
fn add_to_linker<T: Send>(
1452
linker: &mut Linker<T>,
1553
get: impl Fn(&mut Data<T>) -> &mut Self::Data + Send + Sync + Copy + 'static,
1654
) -> Result<()>;
1755

56+
/// Builds new host component runtime data for [`HostComponentsData`].
1857
fn build_data(&self) -> Self::Data;
1958
}
2059

@@ -33,6 +72,9 @@ impl<HC: HostComponent> HostComponent for Arc<HC> {
3372
}
3473
}
3574

75+
/// An opaque handle returned by [`crate::EngineBuilder::add_host_component`]
76+
/// which can be passed to [`HostComponentsData`] to access or set associated
77+
/// [`HostComponent::Data`].
3678
pub struct HostComponentDataHandle<HC: HostComponent> {
3779
idx: usize,
3880
_phantom: PhantomData<fn() -> HC::Data>,
@@ -105,12 +147,21 @@ impl HostComponents {
105147
}
106148
}
107149

150+
/// Holds a heterogenous set of [`HostComponent::Data`]s.
108151
pub struct HostComponentsData {
109152
data: Vec<Option<Box<dyn Any + Send>>>,
110153
data_builders: Arc<Vec<DataBuilder>>,
111154
}
112155

113156
impl HostComponentsData {
157+
/// Sets the [`HostComponent::Data`] for the given `handle`.
158+
pub fn set<HC: HostComponent>(&mut self, handle: HostComponentDataHandle<HC>, data: HC::Data) {
159+
self.data[handle.idx] = Some(Box::new(data));
160+
}
161+
162+
/// Retrieves a mutable reference to [`HostComponent::Data`] for the given `handle`.
163+
///
164+
/// If unset, the data will be initialized with [`HostComponent::build_data`].
114165
pub fn get_or_insert<HC: HostComponent>(
115166
&mut self,
116167
handle: HostComponentDataHandle<HC>,
@@ -122,8 +173,4 @@ impl HostComponentsData {
122173
fn get_or_insert_idx(&mut self, idx: usize) -> &mut Box<dyn Any + Send> {
123174
self.data[idx].get_or_insert_with(|| self.data_builders[idx]())
124175
}
125-
126-
pub fn set<HC: HostComponent>(&mut self, handle: HostComponentDataHandle<HC>, data: HC::Data) {
127-
self.data[handle.idx] = Some(Box::new(data));
128-
}
129176
}

crates/core/src/io.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ use std::sync::{Arc, RwLock};
22

33
use wasi_common::pipe::WritePipe;
44

5+
/// An in-memory stdio output buffer.
56
#[derive(Default)]
67
pub struct OutputBuffer(Arc<RwLock<Vec<u8>>>);
78

89
impl OutputBuffer {
10+
/// Takes the buffered output from this buffer.
911
pub fn take(&mut self) -> Vec<u8> {
1012
std::mem::take(&mut *self.0.write().unwrap())
1113
}

crates/core/src/lib.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
//! Spin core execution engine
2+
//!
3+
//! This crate provides low-level Wasm and WASI functionality required by Spin.
4+
//! Most of this functionality consists of wrappers around [`wasmtime`] and
5+
//! [`wasmtime_wasi`] that narrows the flexibility of `wasmtime` to the set of
6+
//! features used by Spin (such as only supporting `wasmtime`'s async calling style).
7+
8+
#![deny(missing_docs)]
9+
110
mod host_component;
211
mod io;
312
mod limits;
@@ -14,8 +23,12 @@ pub use wasmtime::{self, Instance, Module, Trap};
1423
use self::host_component::{HostComponents, HostComponentsBuilder};
1524

1625
pub use host_component::{HostComponent, HostComponentDataHandle, HostComponentsData};
26+
pub use io::OutputBuffer;
1727
pub use store::{Store, StoreBuilder};
1828

29+
/// Global configuration for `EngineBuilder`.
30+
///
31+
/// This is currently only used for advanced (undocumented) use cases.
1932
pub struct Config {
2033
inner: wasmtime::Config,
2134
}
@@ -37,6 +50,7 @@ impl Default for Config {
3750
}
3851
}
3952

53+
/// Host state data associated with individual [Store]s and [Instance]s.
4054
pub struct Data<T> {
4155
inner: T,
4256
wasi: WasiCtx,
@@ -56,8 +70,12 @@ impl<T> AsMut<T> for Data<T> {
5670
}
5771
}
5872

73+
/// An alias for [`wasmtime::Linker`] specialized to [`Data`].
5974
pub type Linker<T> = wasmtime::Linker<Data<T>>;
6075

76+
/// A builder interface for configuring a new [`Engine`].
77+
///
78+
/// A new [`EngineBuilder`] can be obtained with [`Engine::builder`].
6179
pub struct EngineBuilder<T> {
6280
engine: wasmtime::Engine,
6381
linker: Linker<T>,
@@ -78,13 +96,30 @@ impl<T: Send + Sync> EngineBuilder<T> {
7896
})
7997
}
8098

99+
/// Adds definition(s) to the built [`Engine`].
100+
///
101+
/// This method's signature is meant to be used with
102+
/// [`wit-bindgen`](https://github.com/bytecodealliance/wit-bindgen)'s
103+
/// generated `add_to_linker` functions, e.g.:
104+
///
105+
/// ```ignore
106+
/// wit_bindgen_wasmtime::import!({paths: ["my-interface.wit"], async: *});
107+
/// // ...
108+
/// let mut builder: EngineBuilder<my_interface::MyInterfaceData> = Engine::builder();
109+
/// builder.link_import(my_interface::MyInterface::add_to_linker)?;
110+
/// ```
81111
pub fn link_import(
82112
&mut self,
83113
f: impl FnOnce(&mut Linker<T>, fn(&mut Data<T>) -> &mut T) -> Result<()>,
84114
) -> Result<()> {
85115
f(&mut self.linker, Data::as_mut)
86116
}
87117

118+
/// Adds a [`HostComponent`] to the built [`Engine`].
119+
///
120+
/// Returns a [`HostComponentDataHandle`] which can be passed to
121+
/// [`HostComponentsData`] to access or set associated
122+
/// [`HostComponent::Data`] for an instance.
88123
pub fn add_host_component<HC: HostComponent + Send + Sync + 'static>(
89124
&mut self,
90125
host_component: HC,
@@ -93,6 +128,11 @@ impl<T: Send + Sync> EngineBuilder<T> {
93128
.add_host_component(&mut self.linker, host_component)
94129
}
95130

131+
/// Builds an [`Engine`] from this builder with the given host state data.
132+
///
133+
/// Note that this data will generally go entirely unused, but is needed
134+
/// by the implementation of [`Engine::instantiate_pre`]. If `T: Default`,
135+
/// it is probably preferable to use [`EngineBuilder::build`].
96136
pub fn build_with_data(self, instance_pre_data: T) -> Engine<T> {
97137
let host_components = self.host_components_builder.build();
98138

@@ -112,11 +152,14 @@ impl<T: Send + Sync> EngineBuilder<T> {
112152
}
113153

114154
impl<T: Default + Send + Sync> EngineBuilder<T> {
155+
/// Builds an [`Engine`] from this builder.
115156
pub fn build(self) -> Engine<T> {
116157
self.build_with_data(T::default())
117158
}
118159
}
119160

161+
/// An `Engine` is a global context for the initialization and execution of
162+
/// Spin components.
120163
pub struct Engine<T> {
121164
inner: wasmtime::Engine,
122165
linker: Linker<T>,
@@ -125,14 +168,17 @@ pub struct Engine<T> {
125168
}
126169

127170
impl<T: Send + Sync> Engine<T> {
171+
/// Creates a new [`EngineBuilder`] with the given [`Config`].
128172
pub fn builder(config: &Config) -> Result<EngineBuilder<T>> {
129173
EngineBuilder::new(config)
130174
}
131175

176+
/// Creates a new [`StoreBuilder`].
132177
pub fn store_builder(&self) -> StoreBuilder {
133178
StoreBuilder::new(self.inner.clone(), &self.host_components)
134179
}
135180

181+
/// Creates a new [`InstancePre`] for the given [`Module`].
136182
#[instrument(skip_all)]
137183
pub fn instantiate_pre(&self, module: &Module) -> Result<InstancePre<T>> {
138184
let mut store = self.instance_pre_store.lock().unwrap();
@@ -147,11 +193,15 @@ impl<T> AsRef<wasmtime::Engine> for Engine<T> {
147193
}
148194
}
149195

196+
/// A pre-initialized instance that is ready to be instantiated.
197+
///
198+
/// See [`wasmtime::InstancePre`] for more information.
150199
pub struct InstancePre<T> {
151200
inner: wasmtime::InstancePre<Data<T>>,
152201
}
153202

154203
impl<T: Send + Sync> InstancePre<T> {
204+
/// Instantiates this instance with the given [`Store`].
155205
#[instrument(skip_all)]
156206
pub async fn instantiate_async(&self, store: &mut Store<T>) -> Result<Instance> {
157207
self.inner.instantiate_async(store).await

0 commit comments

Comments
 (0)