pdk_core/host/property/
mod.rs1use classy::extract::FromContext;
8use classy::proxy_wasm::types::Bytes;
9use std::convert::Infallible;
10
11pub use self::properties::*;
12use crate::host::{self};
13use anyhow::format_err;
14
15mod properties;
16
17pub trait PropertyAccessor {
19 fn read_property(&self, path: &[&str]) -> Option<Bytes>;
21
22 fn set_property(&self, path: &[&str], value: &[u8]);
24}
25
26pub struct PropertyMapper<'a> {
28 property_accessor: &'a dyn PropertyAccessor,
29}
30
31impl<'a> PropertyMapper<'a> {
32 fn string_property(&self, path: &[&str]) -> host::Result<Option<String>> {
33 if let Some(bytes) = self.property_accessor.read_property(path) {
34 String::from_utf8(bytes).map(Option::from).map_err(|e| {
35 format_err!("Retrieved value for property {path:?} was not valid: {e:?}")
36 })
37 } else {
38 Ok(None)
39 }
40 }
41
42 pub fn from(property_accessor: &'a dyn PropertyAccessor) -> Self {
43 Self { property_accessor }
44 }
45}
46
47impl dyn PropertyAccessor {
48 #[allow(clippy::should_implement_trait)]
49 pub fn default() -> &'static dyn PropertyAccessor {
50 &impls::Host
51 }
52}
53
54impl<'a> dyn PropertyAccessor + 'a {
55 pub fn request(&'a self) -> RequestInfo<'a> {
56 RequestInfo {
57 mapper: PropertyMapper::from(self),
58 }
59 }
60
61 pub fn source(&'a self) -> SourceInfo<'a> {
62 SourceInfo {
63 mapper: PropertyMapper::from(self),
64 }
65 }
66
67 pub fn destination(&'a self) -> DestinationInfo<'a> {
68 DestinationInfo {
69 mapper: PropertyMapper::from(self),
70 }
71 }
72
73 pub fn tracing(&'a self) -> TracingInfo<'a> {
74 TracingInfo {
75 mapper: PropertyMapper::from(self),
76 }
77 }
78}
79
80pub struct RequestInfo<'a> {
81 mapper: PropertyMapper<'a>,
82}
83
84impl RequestInfo<'_> {
85 pub fn id(&self) -> host::Result<Option<String>> {
86 self.mapper.string_property(REQUEST_ID)
87 }
88
89 pub fn protocol(&self) -> host::Result<Option<String>> {
90 self.mapper.string_property(REQUEST_PROTOCOL)
91 }
92
93 pub fn scheme(&self) -> host::Result<Option<String>> {
94 self.mapper.string_property(REQUEST_SCHEME)
95 }
96}
97
98pub struct SourceInfo<'a> {
99 mapper: PropertyMapper<'a>,
100}
101
102impl SourceInfo<'_> {
103 pub fn address(&self) -> host::Result<Option<String>> {
104 self.mapper.string_property(SOURCE_ADDRESS)
105 }
106}
107
108pub struct DestinationInfo<'a> {
109 mapper: PropertyMapper<'a>,
110}
111
112impl DestinationInfo<'_> {
113 pub fn address(&self) -> host::Result<Option<String>> {
114 self.mapper.string_property(DESTINATION_ADDRESS)
115 }
116}
117
118pub struct TracingInfo<'a> {
119 mapper: PropertyMapper<'a>,
120}
121
122impl TracingInfo<'_> {
123 pub fn id(&self) -> host::Result<Option<String>> {
124 self.mapper.string_property(TRACING_ID_PATH)
125 }
126}
127
128impl<C> FromContext<C> for &'static dyn PropertyAccessor {
129 type Error = Infallible;
130
131 fn from_context(_: &C) -> Result<Self, Self::Error> {
132 Ok(<dyn PropertyAccessor>::default())
133 }
134}
135
136mod impls {
137 use crate::host::property::PropertyAccessor;
138 use classy::proxy_wasm::types::Bytes;
139 use classy::Host as ClassyHost;
140
141 pub(super) struct Host;
142
143 impl PropertyAccessor for Host {
144 fn read_property(&self, path: &[&str]) -> Option<Bytes> {
145 crate::Host.get_property(path.to_vec())
146 }
147
148 fn set_property(&self, path: &[&str], value: &[u8]) {
149 crate::Host.set_property(path.to_vec(), Some(value))
150 }
151 }
152}