/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ //! Utility functions for doubly-linked lists. use mem::HeapSizeOf; use serde::de::{Error, SeqVisitor, Visitor}; use serde::ser::impls::SeqIteratorVisitor; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::collections::LinkedList; use std::marker::PhantomData; use std::mem; use std::ops::{Deref, DerefMut}; pub struct SerializableLinkedList(LinkedList); impl SerializableLinkedList { pub fn new(linked_list: LinkedList) -> SerializableLinkedList { SerializableLinkedList(linked_list) } } impl Deref for SerializableLinkedList { type Target = LinkedList; fn deref(&self) -> &LinkedList { &self.0 } } impl DerefMut for SerializableLinkedList { fn deref_mut(&mut self) -> &mut LinkedList { &mut self.0 } } impl HeapSizeOf for SerializableLinkedList { fn heap_size_of_children(&self) -> usize { self.0.heap_size_of_children() } } impl Serialize for SerializableLinkedList where T: Serialize { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { serializer.visit_seq(SeqIteratorVisitor::new(self.0.iter(), Some(self.0.len()))) } } impl Deserialize for SerializableLinkedList where T: Deserialize { fn deserialize(deserializer: &mut D) -> Result, D::Error> where D: Deserializer { struct SerializableLinkedListVisitor { marker: PhantomData, } impl Visitor for SerializableLinkedListVisitor where T: Deserialize { type Value = SerializableLinkedList; #[inline] fn visit_seq(&mut self, mut visitor: V) -> Result, V::Error> where V: SeqVisitor { let mut list = LinkedList::new(); for _ in 0..visitor.size_hint().0 { match try!(visitor.visit()) { Some(element) => list.push_back(element), None => return Err(Error::end_of_stream_error()), } } try!(visitor.end()); Ok(SerializableLinkedList(list)) } } deserializer.visit_seq(SerializableLinkedListVisitor { marker: PhantomData, }) } } /// Splits the head off a list in O(1) time, and returns the head. pub fn split_off_head(list: &mut LinkedList) -> LinkedList { let tail = list.split_off(1); mem::replace(list, tail) } /// Prepends the items in the other list to this one, leaving the other list empty. #[inline] pub fn prepend_from(this: &mut LinkedList, other: &mut LinkedList) { other.append(this); mem::swap(this, other); }