1use std::borrow::Cow;
2use std::cmp::Ordering;
3use std::fmt;
4use std::hash::{Hash, Hasher};
5use std::marker::PhantomData;
6use std::ops::{Deref, DerefMut};
7
8use deser_core::de::{Deserialize, OwnedSink, Sink, SinkHandle, default_atom};
9use deser_core::ser::SerializeRef;
10use deser_core::ser::{
11 Boxed, Describe, Emit, SerializeHandle, StructEmitter, Variant, VariantKind, VariantRepr,
12};
13use deser_core::{Atom, Error, ErrorKind, Serialize, State, Text};
14
15use crate::Names;
16
17pub struct Mixed<T, W = KeepWhitespace>(pub Vec<T>, PhantomData<fn() -> W>);
128
129pub trait Whitespace: sealed::Sealed + 'static {
133 #[doc(hidden)]
134 const KEEP: bool;
135}
136
137#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
139pub struct KeepWhitespace;
140
141#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
147pub struct SkipWhitespace;
148
149impl Whitespace for KeepWhitespace {
150 const KEEP: bool = true;
151}
152
153impl Whitespace for SkipWhitespace {
154 const KEEP: bool = false;
155}
156
157mod sealed {
158 pub trait Sealed {}
159 impl Sealed for super::KeepWhitespace {}
160 impl Sealed for super::SkipWhitespace {}
161}
162
163impl<T, W> Mixed<T, W> {
164 pub const fn new() -> Mixed<T, W> {
166 Mixed(Vec::new(), PhantomData)
167 }
168
169 pub fn into_inner(self) -> Vec<T> {
171 self.0
172 }
173}
174
175impl<T: fmt::Debug, W> fmt::Debug for Mixed<T, W> {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 f.debug_tuple("Mixed").field(&self.0).finish()
178 }
179}
180
181impl<T: Clone, W> Clone for Mixed<T, W> {
182 fn clone(&self) -> Mixed<T, W> {
183 Mixed(self.0.clone(), PhantomData)
184 }
185}
186
187impl<T: PartialEq, W> PartialEq for Mixed<T, W> {
188 fn eq(&self, other: &Mixed<T, W>) -> bool {
189 self.0 == other.0
190 }
191}
192
193impl<T: Eq, W> Eq for Mixed<T, W> {}
194
195impl<T: PartialOrd, W> PartialOrd for Mixed<T, W> {
196 fn partial_cmp(&self, other: &Mixed<T, W>) -> Option<Ordering> {
197 self.0.partial_cmp(&other.0)
198 }
199}
200
201impl<T: Ord, W> Ord for Mixed<T, W> {
202 fn cmp(&self, other: &Mixed<T, W>) -> Ordering {
203 self.0.cmp(&other.0)
204 }
205}
206
207impl<T: Hash, W> Hash for Mixed<T, W> {
208 fn hash<H: Hasher>(&self, state: &mut H) {
209 self.0.hash(state)
210 }
211}
212
213impl<T, W> Default for Mixed<T, W> {
214 fn default() -> Mixed<T, W> {
215 Mixed::new()
216 }
217}
218
219impl<T, W> Deref for Mixed<T, W> {
220 type Target = Vec<T>;
221
222 fn deref(&self) -> &Vec<T> {
223 &self.0
224 }
225}
226
227impl<T, W> DerefMut for Mixed<T, W> {
228 fn deref_mut(&mut self) -> &mut Vec<T> {
229 &mut self.0
230 }
231}
232
233impl<T, W> From<Vec<T>> for Mixed<T, W> {
234 fn from(values: Vec<T>) -> Mixed<T, W> {
235 Mixed(values, PhantomData)
236 }
237}
238
239impl<T, W> FromIterator<T> for Mixed<T, W> {
240 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Mixed<T, W> {
241 Mixed(iter.into_iter().collect(), PhantomData)
242 }
243}
244
245impl<T, W> IntoIterator for Mixed<T, W> {
246 type Item = T;
247 type IntoIter = std::vec::IntoIter<T>;
248
249 fn into_iter(self) -> Self::IntoIter {
250 self.0.into_iter()
251 }
252}
253
254impl<'a, T, W> IntoIterator for &'a Mixed<T, W> {
255 type Item = &'a T;
256 type IntoIter = std::slice::Iter<'a, T>;
257
258 fn into_iter(self) -> Self::IntoIter {
259 self.0.iter()
260 }
261}
262
263#[derive(Debug, Default)]
270pub(crate) struct WhitespaceDepths(pub(crate) Vec<usize>);
271
272impl WhitespaceDepths {
273 pub(crate) fn applies(state: &State) -> bool {
275 state
276 .get::<WhitespaceDepths>()
277 .and_then(|keep| keep.0.last())
278 .is_some_and(|&depth| depth == state.depth())
279 }
280
281 pub(crate) fn prune(state: &mut State) {
287 let depth = state.depth();
288 if state.get::<WhitespaceDepths>().is_some() {
289 state
290 .get_mut::<WhitespaceDepths>()
291 .0
292 .retain(|&keep| keep <= depth);
293 }
294 }
295}
296
297impl<'de, T: Deserialize<'de>, W: Whitespace> Deserialize<'de> for Mixed<T, W> {
298 fn deserialize_into<'out>(
299 out: &'out mut Option<Self>,
300 state: &mut State,
301 ) -> SinkHandle<'out, 'de> {
302 SinkHandle::arena(
303 MixedSink {
304 out,
305 values: Vec::new(),
306 key: None,
307 pending: None,
308 depth: None,
309 },
310 state,
311 )
312 }
313
314 fn expecting() -> Cow<'static, str> {
315 Cow::Borrowed("mixed content")
316 }
317
318 fn initial_value() -> Option<Self> {
320 Some(Mixed::new())
321 }
322}
323
324struct MixedSink<'a, 'de, T, W> {
325 out: &'a mut Option<Mixed<T, W>>,
326 values: Vec<T>,
327 key: Option<String>,
328 pending: Option<OwnedSink<'de, T>>,
330 depth: Option<usize>,
332}
333
334impl<'de, T: Deserialize<'de>, W: Whitespace> MixedSink<'_, 'de, T, W> {
335 fn keep_whitespace(&mut self, depth: usize, state: &mut State) {
337 if W::KEEP && self.depth.is_none() {
338 self.depth = Some(depth);
339 state.get_mut::<WhitespaceDepths>().0.push(depth);
340 }
341 }
342
343 fn is_content(text: &str) -> bool {
345 if W::KEEP {
346 !text.is_empty()
347 } else {
348 !text.trim().is_empty()
349 }
350 }
351
352 fn begin(&mut self, key: &str, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
354 self.end(state)?;
355 let pending = self.pending.insert(OwnedSink::deserialize(state));
356 let sink = pending.get_mut();
357 sink.map(state)?;
358 let mut key_sink = sink.next_key(state)?;
359 key_sink.atom(Atom::Lexical(Text::borrowed(key)), state)?;
360 key_sink.finish(state)?;
361 drop(key_sink);
362 sink.next_value(state)
363 }
364
365 fn end(&mut self, state: &mut State) -> Result<(), Error> {
369 if let Some(mut pending) = self.pending.take() {
370 pending.get_mut().finish(state)?;
371 self.values.extend(pending.take());
372 }
373 Ok(())
374 }
375}
376
377impl<'de, T: Deserialize<'de>, W: Whitespace> Sink<'de> for MixedSink<'_, 'de, T, W> {
378 fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
381 match atom {
382 Atom::Null => Ok(()),
383 Atom::Str(ref text) | Atom::Lexical(ref text) if !Self::is_content(text) => Ok(()),
384 Atom::Str(_) | Atom::Lexical(_) => {
385 let mut sink = self.begin(text_key(state), state)?;
386 sink.atom(atom, state)?;
387 sink.finish(state)
388 }
389 atom => default_atom(self, atom, state),
390 }
391 }
392
393 fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
394 match atom {
395 Atom::Str(ref text) | Atom::Lexical(ref text) if Self::is_content(text) => {
396 let mut sink = self.begin(text_key(state), state)?;
397 sink.borrowed_atom(atom, state)?;
398 sink.finish(state)
399 }
400 atom => self.atom(atom, state),
401 }
402 }
403
404 fn map(&mut self, state: &mut State) -> Result<(), Error> {
405 self.keep_whitespace(state.depth() + 1, state);
407 Ok(())
408 }
409
410 fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
411 self.end(state)?;
412 Ok(String::deserialize_into(&mut self.key, state))
413 }
414
415 fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
416 let key = self.key.take().unwrap_or_default();
417 Ok(self
418 .value_for_key(&key, state)?
419 .unwrap_or_else(SinkHandle::null))
420 }
421
422 fn value_for_key(
424 &mut self,
425 key: &str,
426 state: &mut State,
427 ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
428 let prefix = names(state).attribute_prefix;
429 if !prefix.is_empty() && key.starts_with(prefix) {
430 return Ok(None);
431 }
432 self.keep_whitespace(state.depth(), state);
434 self.begin(key, state).map(Some)
435 }
436
437 fn finish(&mut self, state: &mut State) -> Result<(), Error> {
438 self.end(state)?;
439 if let Some(depth) = self.depth.take() {
440 let keep = &mut state.get_mut::<WhitespaceDepths>().0;
441 if keep.last() == Some(&depth) {
442 keep.pop();
443 }
444 }
445 *self.out = Some(Mixed(std::mem::take(&mut self.values), PhantomData));
446 Ok(())
447 }
448
449 fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
450 self.key = None;
451 match self.pending {
452 Some(ref mut pending) => pending.get_mut().recover(err, state),
453 None => Err(err),
454 }
455 }
456
457 fn expecting(&self) -> Cow<'_, str> {
458 Cow::Borrowed("mixed content")
459 }
460}
461
462fn names(state: &State) -> &Names {
463 const DEFAULT: Names = Names::new();
464 state.get::<Names>().unwrap_or(&DEFAULT)
465}
466
467fn text_key(state: &State) -> &'static str {
468 names(state).text_key
469}
470
471#[derive(Debug, Default, Clone)]
477pub(crate) struct KeepsWhitespace(pub(crate) bool);
478
479impl<T: Serialize, W: Whitespace> Serialize for Mixed<T, W> {
480 fn serialize<'a>(value: &'a Self, state: &mut State) -> Result<Emit<'a>, Error> {
481 if W::KEEP {
482 state.event_mut::<KeepsWhitespace>().0 = true;
483 }
484 Ok(Emit::structure(
485 MixedEmitter {
486 values: value.0.iter(),
487 current: None,
488 },
489 state,
490 ))
491 }
492}
493
494enum Entries<'a> {
496 Struct(Boxed<dyn StructEmitter + 'a>),
497 Unit(Option<Cow<'a, str>>),
499}
500
501struct MixedEmitter<'a, T> {
502 values: std::slice::Iter<'a, T>,
503 current: Option<(&'a T, Entries<'a>)>,
504}
505
506impl<'a, T: Serialize> StructEmitter for MixedEmitter<'a, T> {
507 fn next(
508 &mut self,
509 state: &mut State,
510 ) -> Result<Option<(Cow<'_, str>, SerializeHandle<'_>)>, Error> {
511 loop {
512 if let Some((_, ref mut entries)) = self.current {
513 let entry = match entries {
514 Entries::Struct(emitter) => emitter.next(state)?,
515 Entries::Unit(name) => name.take().map(|name| (name, SerializeHandle::to(&""))),
516 };
517 let entry = unsafe {
523 std::mem::transmute::<
524 Option<(Cow<'_, str>, SerializeHandle<'_>)>,
525 Option<(Cow<'a, str>, SerializeHandle<'a>)>,
526 >(entry)
527 };
528 if let Some(entry) = entry {
529 return Ok(Some(entry));
530 }
531 let (value, entries) = self.current.take().unwrap();
532 drop(entries);
533 T::finish(value, state)?;
534 }
535 let Some(value) = self.values.next() else {
536 return Ok(None);
537 };
538 let entries = match T::serialize(value, state)? {
539 Emit::Struct(emitter) => Entries::Struct(emitter),
540 Emit::Atom(Atom::Str(name) | Atom::Lexical(name))
541 if is_unit_variant(SerializeRef::new(value)) =>
542 {
543 Entries::Unit(Some(name.into_cow()))
544 }
545 Emit::Atom(Atom::Null) => Entries::Unit(None),
546 _ => {
547 return Err(Error::new(
548 ErrorKind::UnsupportedType,
549 "the values of mixed content must be structs or externally tagged enums",
550 ));
551 }
552 };
553 self.current = Some((value, entries));
554 }
555 }
556}
557
558fn is_unit_variant(value: SerializeRef<'_>) -> bool {
560 struct Check(bool);
561
562 impl Describe for Check {
563 fn variant(&mut self, variant: &Variant<'_>) {
564 self.0 = variant.kind == VariantKind::Unit && variant.repr == VariantRepr::External;
565 }
566 }
567
568 let mut check = Check(false);
569 value.describe(&mut check);
570 check.0
571}