1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
pub use ;
use Serialize;
use cratePresenter;
/// A type that is presentable to a user.
///
/// This is analogous in concept to `std::fmt::Display`, and in implementation
/// to `std::fmt::Debug`, with the difference that instead of formatting an
/// unstyled string, implementations register how they are presented with a
/// [`Presenter`].
///
/// # Implementors
///
/// Currently it is not possible to store `Box<dyn Presentable>`, because of the
/// following:
///
/// * `Presentable` implies `Serialize`.
/// * `Presentable::present<'_, PR>` and `Serialize::serialize<S>` are generic
/// trait methods.
/// * This means different concrete implementations of `Presentable`/`Serialize`
/// will have different vtables (with different sizes), and Rust returns the
/// following compilation error:
///
/// ```text
/// error[E0038]: the trait `Presentable` cannot be made into an object
/// ```
///
/// See <https://doc.rust-lang.org/error_codes/E0038.html>.
///
/// It is possible to store `Vec<Box<T>>` for any `T: Presentable` and invoke
/// `boxed.present()`.
///
/// # Examples
///
/// Presenting a list item with a name and value:
///
/// ```rust
/// # use peace_fmt::{Presentable, Presenter};
/// # use serde::{Deserialize, Serialize};
/// // use peace::fmt::{Presentable, Presenter};
///
/// #[derive(Clone, Deserialize, Serialize)]
/// struct Item {
/// name: String,
/// desc: String,
/// }
///
/// #[async_trait::async_trait(?Send)]
/// impl Presentable for Item {
/// async fn present<'output, PR>(&self, presenter: &mut PR) -> Result<(), PR::Error>
/// where
/// PR: Presenter<'output>,
/// {
/// presenter.name(&self.name).await?;
/// presenter.text(": ").await?;
/// presenter.text(&self.desc).await?;
/// Ok(())
/// }
/// }
/// ```
///
/// # Design
///
/// `Presentable` implies `Serialize` because it is beneficial for anything that
/// is presented to the user, to be able to be stored, so that it can be
/// re-presented to them at a later time. However, it currently doesn't imply
/// `DeserializeOwned`, which may mean the serialization half may not be
/// worthwhile, and `Presentable` wrapper types may just wrap borrowed data.
///
/// Previously, this was implemented as `Presentable: Serialize +
/// OwnedDeserialize`, with `OwnedDeserialize` being the following trait:
///
/// ```rust
/// use serde::de::DeserializeOwned;
///
/// /// Marker trait to allow `str` to implement `Presentable`.
/// ///
/// /// 1. `str` is not an owned type, so it doesn't `impl DeserializeOwned`.
/// /// 2. We don't want to relax the constraints such that `Presentable` doesn't
/// /// imply `DeserializeOwned`.
/// pub trait OwnedDeserialize {}
///
/// impl<T> OwnedDeserialize for T
/// where
/// T: ToOwned + ?Sized,
/// <T as ToOwned>::Owned: DeserializeOwned,
/// {
/// }
/// ```
///
/// However, because stateful deserialized types such as `TypeMap` don't
/// implement `DeserializeOwned`, so any types based on that such as `States`
/// would not be able to implement `Presentable` with this bound.