smoldot_light/platform/
with_prefix.rs

1// Smoldot
2// Copyright (C) 2024  Pierre Krieger
3// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18use core::{iter, pin::Pin};
19
20use super::{Address, ConnectionType, LogLevel, MultiStreamAddress, PlatformRef};
21use alloc::{borrow::Cow, format, string::String};
22
23/// Implementation of a [`PlatformRef`] that wraps around another platform and adds a prefix
24/// before every log line and task name.
25#[derive(Debug, Clone)]
26pub struct WithPrefix<T> {
27    inner: T,
28    prefix: String,
29}
30
31impl<T> WithPrefix<T> {
32    /// Builds a new [`WithPrefix`].
33    pub const fn new(prefix: String, inner: T) -> Self {
34        WithPrefix { inner, prefix }
35    }
36}
37
38impl<T: PlatformRef> PlatformRef for WithPrefix<T> {
39    type Delay = T::Delay;
40    type Instant = T::Instant;
41    type MultiStream = T::MultiStream;
42    type Stream = T::Stream;
43    type ReadWriteAccess<'a> = T::ReadWriteAccess<'a>;
44    type StreamErrorRef<'a> = T::StreamErrorRef<'a>;
45    type StreamConnectFuture = T::StreamConnectFuture;
46    type MultiStreamConnectFuture = T::MultiStreamConnectFuture;
47    type StreamUpdateFuture<'a> = T::StreamUpdateFuture<'a>;
48    type NextSubstreamFuture<'a> = T::NextSubstreamFuture<'a>;
49
50    fn now_from_unix_epoch(&self) -> core::time::Duration {
51        self.inner.now_from_unix_epoch()
52    }
53
54    fn now(&self) -> Self::Instant {
55        self.inner.now()
56    }
57
58    fn fill_random_bytes(&self, buffer: &mut [u8]) {
59        self.inner.fill_random_bytes(buffer)
60    }
61
62    fn sleep(&self, duration: core::time::Duration) -> Self::Delay {
63        self.inner.sleep(duration)
64    }
65
66    fn sleep_until(&self, when: Self::Instant) -> Self::Delay {
67        self.inner.sleep_until(when)
68    }
69
70    fn spawn_task(&self, task_name: Cow<str>, task: impl Future<Output = ()> + Send + 'static) {
71        self.inner
72            .spawn_task(Cow::Owned(format!("{}-{}", self.prefix, task_name)), task)
73    }
74
75    fn log<'a>(
76        &self,
77        log_level: LogLevel,
78        log_target: &'a str,
79        message: &'a str,
80        mut key_values: impl Iterator<Item = (&'a str, &'a dyn core::fmt::Display)>,
81    ) {
82        self.inner.log(
83            log_level,
84            &format!("{}-{}", self.prefix, log_target),
85            message,
86            // We have to use `iter::from_fn` due to a lifetime mismatch between the items
87            // produced by the iterator and the newly-constructed log target.
88            iter::from_fn(move || key_values.next()),
89        )
90    }
91
92    fn client_name(&self) -> Cow<str> {
93        self.inner.client_name()
94    }
95
96    fn client_version(&self) -> Cow<str> {
97        self.inner.client_version()
98    }
99
100    fn supports_connection_type(&self, connection_type: ConnectionType) -> bool {
101        self.inner.supports_connection_type(connection_type)
102    }
103
104    fn connect_stream(&self, address: Address) -> Self::StreamConnectFuture {
105        self.inner.connect_stream(address)
106    }
107
108    fn connect_multistream(&self, address: MultiStreamAddress) -> Self::MultiStreamConnectFuture {
109        self.inner.connect_multistream(address)
110    }
111
112    fn open_out_substream(&self, connection: &mut Self::MultiStream) {
113        self.inner.open_out_substream(connection)
114    }
115
116    fn next_substream<'a>(
117        &self,
118        connection: &'a mut Self::MultiStream,
119    ) -> Self::NextSubstreamFuture<'a> {
120        self.inner.next_substream(connection)
121    }
122
123    fn read_write_access<'a>(
124        &self,
125        stream: Pin<&'a mut Self::Stream>,
126    ) -> Result<Self::ReadWriteAccess<'a>, Self::StreamErrorRef<'a>> {
127        self.inner.read_write_access(stream)
128    }
129
130    fn wait_read_write_again<'a>(
131        &self,
132        stream: Pin<&'a mut Self::Stream>,
133    ) -> Self::StreamUpdateFuture<'a> {
134        self.inner.wait_read_write_again(stream)
135    }
136}