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::{
7    FunctionResult,
8    encoding::{Encode, Json},
9};
10
11/// Publish a message to a topic in the cache this Function is running within.
12///
13/// Examples:
14/// _________
15/// String:
16/// ```rust
17/// # use momento_functions_host::FunctionResult;
18/// # use momento_functions_host::topics;
19///
20/// # fn f() -> FunctionResult<()> {
21/// topics::publish("my_topic", "hello there")?;
22/// # Ok(()) }
23/// ```
24/// ________
25/// Bytes:
26/// ```rust
27/// # use momento_functions_host::FunctionResult;
28/// # use momento_functions_host::topics;
29///
30/// # fn f() -> FunctionResult<()> {
31/// topics::publish("my_topic", b"hello there".to_vec())?;
32/// # Ok(()) }
33/// ```
34/// ________
35/// Json:
36/// ```rust
37/// # use momento_functions_host::FunctionResult;
38/// # use momento_functions_host::topics;
39/// use momento_functions_host::encoding::Json;
40///
41/// #[derive(serde::Serialize)]
42/// struct MyStruct {
43///    hello: String
44/// }
45///
46/// # fn f() -> FunctionResult<()> {
47/// topics::publish("my_topic", Json(MyStruct{ hello: "hello".to_string() }))?;
48/// # Ok(()) }
49/// ```
50pub fn publish<T: for<'a> PublishKind<'a>>(topic: impl AsRef<str>, value: T) -> FunctionResult<()> {
51    match value.as_publish()? {
52        Publish::Str(s) => topic::publish(topic.as_ref(), s),
53        Publish::String(s) => topic::publish(topic.as_ref(), s.as_str()),
54        Publish::Bytes(b) => topic::publish_bytes(topic.as_ref(), &b.try_serialize()?.into()),
55    }
56    .map_err(Into::into)
57}
58
59/// Bind a type to a kind of topic message
60pub trait PublishKind<'a> {
61    /// Type of payload to publish
62    type Encoding: Encode;
63
64    /// Convert this type into a publishable message
65    fn as_publish(&'a self) -> FunctionResult<Publish<'a, Self::Encoding>>;
66}
67impl<'a> PublishKind<'a> for String {
68    type Encoding = &'a [u8];
69
70    fn as_publish(&'a self) -> FunctionResult<Publish<'a, Self::Encoding>> {
71        Ok(Publish::Str(self))
72    }
73}
74impl<'a> PublishKind<'a> for &str {
75    type Encoding = &'a [u8];
76
77    fn as_publish(&'a self) -> FunctionResult<Publish<'a, Self::Encoding>> {
78        Ok(Publish::Str(self))
79    }
80}
81impl<'a> PublishKind<'a> for &[u8] {
82    type Encoding = &'a [u8];
83
84    fn as_publish(&'a self) -> FunctionResult<Publish<'a, Self::Encoding>> {
85        Ok(Publish::Bytes(self))
86    }
87}
88impl<'a> PublishKind<'a> for Vec<u8> {
89    type Encoding = &'a [u8];
90
91    fn as_publish(&'a self) -> FunctionResult<Publish<'a, Self::Encoding>> {
92        Ok(Publish::Bytes(self.as_slice()))
93    }
94}
95impl<'a, T: Serialize> PublishKind<'a> for Json<T> {
96    type Encoding = &'a [u8];
97
98    fn as_publish(&'a self) -> FunctionResult<Publish<'a, Self::Encoding>> {
99        serde_json::to_string(&self.0)
100            .map_err(|e| crate::Error::MessageError(format!("failed to serialize json: {e}")))
101            .map(Publish::String)
102    }
103}
104
105/// Value to publish to a topic.
106/// You can publish a string or bytes.
107pub enum Publish<'a, P: Encode = &'a [u8]> {
108    /// Publish a string to the topic
109    Str(&'a str),
110    /// Publish a string to the topic
111    String(String),
112    /// Publish encoded bytes to the topic
113    Bytes(P),
114}