momento_functions_host/
topics.rs

1//! Host interfaces for working with Momento Topics apis
2
3use momento_functions_wit::host::momento::functions::topic;
4use serde::Serialize;
5
6use crate::encoding::{Encode, EncodeError, Json};
7
8/// An error occurred while publihsing to a topic.
9#[derive(Debug, thiserror::Error)]
10pub enum PublishError<E: EncodeError> {
11    /// An error occurred while encoding the provided message.
12    #[error("Failed to encode message")]
13    EncodeFailed {
14        /// The underlying encoding error.
15        cause: E,
16    },
17    /// An error occurred while calling the host publish function.
18    #[error(transparent)]
19    PublishError(#[from] topic::Error),
20}
21
22/// Publish a message to a topic in the cache this Function is running within.
23///
24/// Examples:
25/// _________
26/// String:
27/// ```rust
28/// # use momento_functions_host::topics;///
29/// #
30/// use momento_functions_host::topics::PublishError;
31///
32/// fn f() -> Result<(), PublishError<&'static str>> {
33/// topics::publish("my_topic", "hello there")?;
34/// # Ok(()) }
35/// ```
36/// ________
37/// Bytes:
38/// ```rust
39/// # use momento_functions_host::topics;///
40/// #
41/// use momento_functions_host::topics::PublishError;
42///
43/// fn f() -> Result<(), PublishError<&'static str>> {
44/// topics::publish("my_topic", b"hello there".to_vec())?;
45/// # Ok(()) }
46/// ```
47/// ________
48/// Json:
49/// ```rust
50/// # use momento_functions_host::topics;
51/// use momento_functions_host::encoding::Json;///
52///
53/// use momento_functions_host::topics::PublishError;
54///
55/// #[derive(serde::Serialize)]
56/// struct MyStruct {
57///    hello: String
58/// }
59///
60/// # fn f() -> Result<(), PublishError<Json<MyStruct>>> {
61/// topics::publish("my_topic", Json(MyStruct{ hello: "hello".to_string() }))?;
62/// # Ok(()) }
63/// ```
64pub fn publish<T: PublishKind>(
65    topic: impl AsRef<str>,
66    value: T,
67) -> Result<(), PublishError<<<T as PublishKind>::Encoding as Encode>::Error>> {
68    match value
69        .as_publish()
70        .map_err(|e| PublishError::EncodeFailed { cause: e })?
71    {
72        Publish::Str(s) => topic::publish(topic.as_ref(), s),
73        Publish::String(s) => topic::publish(topic.as_ref(), s.as_str()),
74        Publish::Bytes(b) => topic::publish_bytes(
75            topic.as_ref(),
76            &b.try_serialize()
77                .map_err(|e| PublishError::EncodeFailed { cause: e })?
78                .into(),
79        ),
80    }
81    .map_err(Into::into)
82}
83
84/// Bind a type to a kind of topic message
85pub trait PublishKind {
86    /// Type of payload to publish
87    type Encoding: Encode;
88
89    /// Convert this type into a publishable message
90    fn as_publish(&self) -> Result<Publish<'_, Self::Encoding>, <Self::Encoding as Encode>::Error>;
91}
92impl PublishKind for String {
93    type Encoding = String;
94
95    fn as_publish(&self) -> Result<Publish<'_, Self::Encoding>, <Self::Encoding as Encode>::Error> {
96        Ok(Publish::Str(self))
97    }
98}
99impl<'a> PublishKind for &'a str {
100    type Encoding = &'a str;
101
102    fn as_publish(&self) -> Result<Publish<'a, Self::Encoding>, <Self::Encoding as Encode>::Error> {
103        Ok(Publish::Str(self))
104    }
105}
106impl<'a> PublishKind for &'a [u8] {
107    type Encoding = &'a [u8];
108
109    fn as_publish(&self) -> Result<Publish<'a, Self::Encoding>, <Self::Encoding as Encode>::Error> {
110        Ok(Publish::Bytes(self))
111    }
112}
113impl PublishKind for Vec<u8> {
114    type Encoding = Vec<u8>;
115
116    fn as_publish(&self) -> Result<Publish<'_, Self::Encoding>, <Self::Encoding as Encode>::Error> {
117        Ok(Publish::Bytes(self.clone()))
118    }
119}
120impl<T: Serialize> PublishKind for Json<T> {
121    type Encoding = Json<T>;
122
123    fn as_publish(&self) -> Result<Publish<'_, Self::Encoding>, <Self::Encoding as Encode>::Error> {
124        serde_json::to_string(&self.0).map(Publish::String)
125    }
126}
127
128/// Value to publish to a topic.
129/// You can publish a string or bytes.
130pub enum Publish<'a, P: Encode = &'a [u8]> {
131    /// Publish a string to the topic
132    Str(&'a str),
133    /// Publish a string to the topic
134    String(String),
135    /// Publish encoded bytes to the topic
136    Bytes(P),
137}