1use std::borrow::{Borrow, Cow};
2use std::ffi::{OsStr, OsString};
3
4use crate::Monoid;
5
6pub trait PreMonoidBorrowed {
17 type MonoidOwned: Monoid + Borrow<Self>;
19}
20
21pub trait MonoidBorrowed: PreMonoidBorrowed {
33 fn combine_borrowed(&self, rhs: &Self) -> Self::MonoidOwned;
35
36 #[inline]
40 fn combine_left_borrowed(&self, rhs: Self::MonoidOwned) -> Self::MonoidOwned {
41 self.combine_borrowed(rhs.borrow())
42 }
43
44 #[inline]
48 fn combine_right_borrowed(lhs: Self::MonoidOwned, rhs: &Self) -> Self::MonoidOwned {
49 lhs.borrow().combine_borrowed(rhs)
50 }
51
52 fn combine_left_borrowed_assign_to(lhs: &Self, rhs: &mut Self::MonoidOwned) {
54 *rhs = Self::combine_borrowed(lhs, (*rhs).borrow());
55 }
56
57 fn combine_right_borrowed_assign(lhs: &mut Self::MonoidOwned, rhs: &Self) {
59 *lhs = Self::combine_borrowed((*lhs).borrow(), rhs);
60 }
61
62 fn combine_iter_borrowed<'a, I: Iterator<Item = &'a Self>>(iter: I) -> Self::MonoidOwned
65 where
66 Self: 'a,
67 {
68 iter.fold(Monoid::ident(), Self::combine_right_borrowed)
69 }
70
71 fn combine_iter_cow<'a, I: Iterator<Item = Cow<'a, Self>>>(iter: I) -> Self::MonoidOwned
75 where
76 Self: 'a + ToOwned<Owned = Self::MonoidOwned>,
77 {
78 iter.reduce(Cow::combine)
79 .map_or_else(Monoid::ident, Cow::into_owned)
80 }
81}
82
83impl<M: Monoid> PreMonoidBorrowed for M {
84 type MonoidOwned = Self;
85}
86
87impl<M: Monoid + Clone> MonoidBorrowed for M {
88 fn combine_borrowed(&self, rhs: &Self) -> Self::MonoidOwned {
89 self.clone().combine(rhs.clone())
90 }
91
92 fn combine_right_borrowed_assign(lhs: &mut Self::MonoidOwned, rhs: &Self) {
93 lhs.combine_assign(rhs.clone())
94 }
95
96 fn combine_left_borrowed_assign_to(lhs: &Self, rhs: &mut Self::MonoidOwned) {
97 lhs.clone().combine_assign_to(rhs)
98 }
99}
100
101impl<'a, M: 'a + ?Sized + MonoidBorrowed + ToOwned<Owned = M::MonoidOwned>> Monoid for Cow<'a, M> {
103 #[inline]
104 fn ident() -> Self {
105 Cow::Owned(M::MonoidOwned::ident())
106 }
107
108 fn combine(self, rhs: Self) -> Self {
109 Cow::Owned(match (self, rhs) {
110 (Cow::Owned(lhs), Cow::Owned(rhs)) => lhs.combine(rhs),
111 (Cow::Borrowed(lhs), Cow::Owned(rhs)) => lhs.combine_left_borrowed(rhs),
112 (Cow::Owned(lhs), Cow::Borrowed(rhs)) => M::combine_right_borrowed(lhs, rhs),
113 (Cow::Borrowed(lhs), Cow::Borrowed(rhs)) => lhs.combine_borrowed(rhs),
114 })
115 }
116
117 fn combine_assign(&mut self, rhs: Self) {
118 match (&mut *self, rhs) {
119 (Cow::Owned(lhs), Cow::Owned(rhs)) => lhs.combine_assign(rhs),
120 (Cow::Owned(lhs), Cow::Borrowed(rhs)) => M::combine_right_borrowed_assign(lhs, rhs),
121 (Cow::Borrowed(lhs), rhs) => {
122 *self = Cow::Owned(match rhs {
123 Cow::Owned(rhs) => lhs.combine_left_borrowed(rhs),
124 Cow::Borrowed(rhs) => lhs.combine_borrowed(rhs),
125 });
126 }
127 }
128 }
129
130 fn combine_assign_to(self, rhs: &mut Self) {
131 match (self, &mut *rhs) {
132 (Cow::Owned(lhs), Cow::Owned(rhs)) => lhs.combine_assign_to(rhs),
133 (Cow::Borrowed(lhs), Cow::Owned(rhs)) => M::combine_left_borrowed_assign_to(lhs, rhs),
134 (lhs, Cow::Borrowed(r)) => {
135 *rhs = Cow::Owned(match lhs {
136 Cow::Owned(lhs) => M::combine_right_borrowed(lhs, r),
137 Cow::Borrowed(lhs) => lhs.combine_borrowed(r),
138 });
139 }
140 }
141 }
142
143 #[inline]
144 fn combine_iter<I: Iterator<Item = Self>>(iter: I) -> Self {
145 Cow::Owned(M::combine_iter_cow(iter))
146 }
147}
148
149impl<T> PreMonoidBorrowed for [T] {
150 type MonoidOwned = Vec<T>;
151}
152
153impl<T: Clone> MonoidBorrowed for [T] {
154 #[inline]
155 fn combine_borrowed(&self, rhs: &Self) -> Self::MonoidOwned {
156 Self::combine_right_borrowed(self.to_vec(), rhs)
157 }
158
159 #[inline]
160 fn combine_right_borrowed(mut lhs: Self::MonoidOwned, rhs: &Self) -> Self::MonoidOwned {
161 lhs.extend_from_slice(rhs);
162 lhs
163 }
164
165 #[inline]
166 fn combine_right_borrowed_assign(lhs: &mut Self::MonoidOwned, rhs: &Self) {
167 lhs.extend_from_slice(rhs);
168 }
169}
170
171impl PreMonoidBorrowed for str {
172 type MonoidOwned = String;
173}
174
175impl MonoidBorrowed for str {
176 #[inline]
177 fn combine_borrowed(&self, rhs: &Self) -> Self::MonoidOwned {
178 self.to_string() + rhs
179 }
180
181 #[inline]
182 fn combine_right_borrowed(lhs: Self::MonoidOwned, rhs: &Self) -> Self::MonoidOwned {
183 lhs + rhs
184 }
185
186 #[inline]
187 fn combine_right_borrowed_assign(lhs: &mut Self::MonoidOwned, rhs: &Self) {
188 lhs.push_str(rhs);
189 }
190
191 #[inline]
192 fn combine_iter_borrowed<'a, I: Iterator<Item = &'a Self>>(iter: I) -> Self::MonoidOwned {
193 iter.collect()
194 }
195
196 #[inline]
197 fn combine_iter_cow<'a, I: Iterator<Item = Cow<'a, Self>>>(iter: I) -> Self::MonoidOwned {
198 iter.collect()
199 }
200}
201
202impl PreMonoidBorrowed for OsStr {
203 type MonoidOwned = OsString;
204}
205
206impl MonoidBorrowed for OsStr {
207 #[inline]
208 fn combine_borrowed(&self, rhs: &Self) -> Self::MonoidOwned {
209 Self::combine_right_borrowed(self.to_os_string(), rhs)
210 }
211
212 #[inline]
213 fn combine_right_borrowed(mut lhs: Self::MonoidOwned, rhs: &Self) -> Self::MonoidOwned {
214 lhs.push(rhs);
215 lhs
216 }
217
218 #[inline]
219 fn combine_right_borrowed_assign(lhs: &mut Self::MonoidOwned, rhs: &Self) {
220 lhs.push(rhs);
221 }
222
223 #[inline]
224 fn combine_iter_borrowed<'a, I: Iterator<Item = &'a Self>>(iter: I) -> Self::MonoidOwned {
225 iter.collect()
226 }
227
228 #[inline]
229 fn combine_iter_cow<'a, I: Iterator<Item = Cow<'a, Self>>>(iter: I) -> Self::MonoidOwned {
230 iter.collect()
231 }
232}