Skip to content

Commit 47a89c7

Browse files
committed
Deduplicate App::get_metadata, AppComponent::get_metadata
Also add AppComponent::require_metadata for interface consistency. Signed-off-by: Lann Martin <[email protected]>
1 parent 6934177 commit 47a89c7

File tree

2 files changed

+44
-21
lines changed

2 files changed

+44
-21
lines changed

crates/app/src/lib.rs

+14-20
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use spin_core::{wasmtime, Engine, EngineBuilder, StoreBuilder};
1616

1717
use host_component::DynamicHostComponents;
1818
use locked::{ContentPath, LockedApp, LockedComponent, LockedComponentSource, LockedTrigger};
19+
use values::MetadataExt;
1920

2021
pub use async_trait::async_trait;
2122
pub use host_component::DynamicHostComponent;
@@ -141,20 +142,15 @@ impl<'a> App<'a> {
141142
/// `Err` only if there _is_ a value for the `key` but the typed
142143
/// deserialization failed.
143144
pub fn get_metadata<'this, T: Deserialize<'this>>(&'this self, key: &str) -> Result<Option<T>> {
144-
self.locked
145-
.metadata
146-
.get(key)
147-
.map(|value| Ok(T::deserialize(value)?))
148-
.transpose()
145+
self.locked.metadata.get_typed(key)
149146
}
150147

151148
/// Deserializes typed metadata for this app.
152149
///
153-
/// Like [`App::get_metadata`], but returns an `Err` if there is no metadata
154-
/// for the given `key`.
150+
/// Like [`App::get_metadata`], but returns an error if there is
151+
/// no metadata for the given `key`.
155152
pub fn require_metadata<'this, T: Deserialize<'this>>(&'this self, key: &str) -> Result<T> {
156-
self.get_metadata(key)?
157-
.ok_or_else(|| Error::MetadataError(format!("missing required {key:?}")))
153+
self.locked.metadata.require_typed(key)
158154
}
159155

160156
/// Returns an iterator of custom config [`Variable`]s defined for this app.
@@ -223,17 +219,15 @@ impl<'a> AppComponent<'a> {
223219
/// `Err` only if there _is_ a value for the `key` but the typed
224220
/// deserialization failed.
225221
pub fn get_metadata<T: Deserialize<'a>>(&self, key: &str) -> Result<Option<T>> {
226-
self.locked
227-
.metadata
228-
.get(key)
229-
.map(|value| {
230-
T::deserialize(value).map_err(|err| {
231-
Error::MetadataError(format!(
232-
"failed to deserialize {key:?} = {value:?}: {err:?}"
233-
))
234-
})
235-
})
236-
.transpose()
222+
self.locked.metadata.get_typed(key)
223+
}
224+
225+
/// Deserializes typed metadata for this component.
226+
///
227+
/// Like [`AppComponent::get_metadata`], but returns an error if there is
228+
/// no metadata for the given `key`.
229+
pub fn require_metadata<'this, T: Deserialize<'this>>(&'this self, key: &str) -> Result<T> {
230+
self.locked.metadata.require_typed(key)
237231
}
238232

239233
/// Returns an iterator of custom config values for this component.

crates/app/src/values.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! Dynamically-typed value helpers.
22
3-
use serde::Serialize;
3+
use serde::{Deserialize, Serialize};
44
use serde_json::Value;
55

6+
use crate::Error;
7+
68
/// A String-keyed map with dynamically-typed values.
79
pub type ValuesMap = serde_json::Map<String, Value>;
810

@@ -69,3 +71,30 @@ impl ValuesMapBuilder {
6971
std::mem::take(&mut self.0)
7072
}
7173
}
74+
75+
pub(crate) trait MetadataExt {
76+
fn get_value(&self, key: impl AsRef<str>) -> Option<&Value>;
77+
78+
fn get_typed<'a, T: Deserialize<'a>>(
79+
&'a self,
80+
key: impl AsRef<str>,
81+
) -> Result<Option<T>, Error> {
82+
let key = key.as_ref();
83+
self.get_value(key)
84+
.map(|value| T::deserialize(value))
85+
.transpose()
86+
.map_err(|err| Error::MetadataError(format!("invalid value for {key:?}: {err:?}")))
87+
}
88+
89+
fn require_typed<'a, T: Deserialize<'a>>(&'a self, key: impl AsRef<str>) -> Result<T, Error> {
90+
let key = key.as_ref();
91+
self.get_typed(key)?
92+
.ok_or_else(|| Error::MetadataError(format!("missing required {key:?}")))
93+
}
94+
}
95+
96+
impl MetadataExt for ValuesMap {
97+
fn get_value(&self, key: impl AsRef<str>) -> Option<&Value> {
98+
self.get(key.as_ref())
99+
}
100+
}

0 commit comments

Comments
 (0)