penumbra_sdk_proto/state/
read.rs

1use crate::{DomainType, Message};
2
3use anyhow::Result;
4use cnidarium::StateRead;
5use futures::{Stream, StreamExt};
6use std::{fmt::Debug, pin::Pin};
7
8use super::future::{DomainFuture, ProtoFuture};
9
10pub trait StateReadProto: StateRead + Send + Sync {
11    /// Gets a value from the verifiable key-value store as a domain type.
12    ///
13    /// # Returns
14    ///
15    /// * `Ok(Some(v))` if the value is present and parseable as a domain type `D`;
16    /// * `Ok(None)` if the value is missing;
17    /// * `Err(_)` if the value is present but not parseable as a domain type `D`, or if an underlying storage error occurred.
18    fn get<D>(&self, key: &str) -> DomainFuture<D, Self::GetRawFut>
19    where
20        D: DomainType + std::fmt::Debug,
21        anyhow::Error: From<<D as TryFrom<D::Proto>>::Error>,
22    {
23        DomainFuture {
24            inner: self.get_raw(key),
25            _marker: std::marker::PhantomData,
26        }
27    }
28
29    /// Gets a value from the nonverifiable key-value store as a domain type.
30    ///
31    /// # Returns
32    ///
33    /// * `Ok(Some(v))` if the value is present and parseable as a domain type `D`;
34    /// * `Ok(None)` if the value is missing;
35    /// * `Err(_)` if the value is present but not parseable as a domain type `D`, or if an underlying storage error occurred.
36    fn nonverifiable_get<D>(&self, key: &[u8]) -> DomainFuture<D, Self::GetRawFut>
37    where
38        D: DomainType + std::fmt::Debug,
39        anyhow::Error: From<<D as TryFrom<D::Proto>>::Error>,
40    {
41        DomainFuture {
42            inner: self.nonverifiable_get_raw(key),
43            _marker: std::marker::PhantomData,
44        }
45    }
46
47    /// Gets a value from the verifiable key-value store as a proto type.
48    ///
49    /// # Returns
50    ///
51    /// * `Ok(Some(v))` if the value is present and parseable as a proto type `P`;
52    /// * `Ok(None)` if the value is missing;
53    /// * `Err(_)` if the value is present but not parseable as a proto type `P`, or if an underlying storage error occurred.
54    fn get_proto<P>(&self, key: &str) -> ProtoFuture<P, Self::GetRawFut>
55    where
56        P: Message + Default + Debug,
57    {
58        ProtoFuture {
59            inner: self.get_raw(key),
60            _marker: std::marker::PhantomData,
61        }
62    }
63
64    /// Gets a value from the nonverifiable key-value store as a proto type.
65    ///
66    /// # Returns
67    ///
68    /// * `Ok(Some(v))` if the value is present and parseable as a proto type `P`;
69    /// * `Ok(None)` if the value is missing;
70    /// * `Err(_)` if the value is present but not parseable as a proto type `P`, or if an underlying storage error occurred.
71    fn nonverifiable_get_proto<P>(&self, key: &[u8]) -> ProtoFuture<P, Self::GetRawFut>
72    where
73        P: Message + Default + Debug,
74    {
75        ProtoFuture {
76            inner: self.nonverifiable_get_raw(key),
77            _marker: std::marker::PhantomData,
78        }
79    }
80
81    /// Retrieve all values for keys matching a prefix from consensus-critical state, as domain types.
82    #[allow(clippy::type_complexity)]
83    fn prefix<'a, D>(
84        &'a self,
85        prefix: &'a str,
86    ) -> Pin<Box<dyn Stream<Item = Result<(String, D)>> + Send + 'static>>
87    where
88        D: DomainType,
89        anyhow::Error: From<<D as TryFrom<D::Proto>>::Error>,
90    {
91        Box::pin(self.prefix_proto(prefix).map(|p| match p {
92            Ok(p) => match D::try_from(p.1) {
93                Ok(d) => Ok((p.0, d)),
94                Err(e) => Err(e.into()),
95            },
96            Err(e) => Err(e),
97        }))
98    }
99
100    /// Retrieve all values for keys matching a prefix from nonverifiable storage, as domain types.
101    #[allow(clippy::type_complexity)]
102    fn nonverifiable_prefix<'a, D>(
103        &'a self,
104        prefix: &[u8],
105    ) -> Pin<Box<dyn Stream<Item = Result<(Vec<u8>, D)>> + Send + 'static>>
106    where
107        D: DomainType,
108        anyhow::Error: From<<D as TryFrom<D::Proto>>::Error>,
109    {
110        Box::pin(self.nonverifiable_prefix_proto(prefix).map(|p| match p {
111            Ok(p) => match D::try_from(p.1) {
112                Ok(d) => Ok((p.0, d)),
113                Err(e) => Err(e.into()),
114            },
115            Err(e) => Err(e),
116        }))
117    }
118
119    /// Retrieve all values for keys matching a prefix from the verifiable key-value store, as proto types.
120    #[allow(clippy::type_complexity)]
121    fn prefix_proto<'a, P>(
122        &'a self,
123        prefix: &'a str,
124    ) -> Pin<Box<dyn Stream<Item = Result<(String, P)>> + Send + 'static>>
125    where
126        P: Message + Default,
127    {
128        let o = self.prefix_raw(prefix).map(|r| {
129            r.and_then(|(key, bytes)| {
130                Ok((
131                    key,
132                    Message::decode(&*bytes).map_err(|e| anyhow::anyhow!(e))?,
133                ))
134            })
135        });
136        Box::pin(o)
137    }
138
139    /// Retrieve all values for keys matching a prefix from the nonverifiable key-value store, as proto types.
140    #[allow(clippy::type_complexity)]
141    fn nonverifiable_prefix_proto<'a, P>(
142        &'a self,
143        prefix: &'a [u8],
144    ) -> Pin<Box<dyn Stream<Item = Result<(Vec<u8>, P)>> + Send + 'static>>
145    where
146        P: Message + Default,
147    {
148        let o = self.nonverifiable_prefix_raw(prefix).map(|r| {
149            r.and_then(|(key, bytes)| {
150                Ok((
151                    key,
152                    Message::decode(&*bytes).map_err(|e| anyhow::anyhow!(e))?,
153                ))
154            })
155        });
156        Box::pin(o)
157    }
158}
159impl<T: StateRead + ?Sized> StateReadProto for T {}