/* 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 std::collections::DList; use std::mem; use std::ptr; struct RawDList { length: uint, head: Option>>, tail: *mut RawNode, } #[allow(dead_code)] struct RawNode { next: Option>>, prev: *mut RawNode, value: T, } #[unsafe_destructor] impl Drop for RawDList { fn drop(&mut self) { fail!("shouldn't happen") } } /// Workaround for a missing method on Rust's `DList` type. Splits the head off a list in O(1) /// time. pub fn split(list: &mut DList) -> DList { let list = unsafe { mem::transmute::<&mut DList,&mut RawDList>(list) }; if list.length == 0 { fail!("split_dlist(): empty list") } let mut head_node = mem::replace(&mut list.head, None); let head_node_ptr: *mut RawNode = &mut **head_node.as_mut().unwrap(); let mut head_list = RawDList { length: 1, head: head_node, tail: head_node_ptr, }; debug_assert!(list.head.is_none()); mem::swap(&mut head_list.head.as_mut().unwrap().next, &mut list.head); debug_assert!(head_list.head.as_mut().unwrap().next.is_none()); debug_assert!(head_list.head.as_mut().unwrap().prev.is_null()); head_list.head.as_mut().unwrap().prev = ptr::null_mut(); list.length -= 1; if list.length == 0 { list.tail = ptr::null_mut() } else { if list.length == 1 { list.tail = &mut **list.head.as_mut().unwrap() as *mut RawNode } list.head.as_mut().unwrap().prev = ptr::null_mut() } unsafe { mem::transmute::,DList>(head_list) } }