diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 291b66939e5ef..b42f68503aac6 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -29,6 +29,7 @@ use Bound::{self, Included, Excluded, Unbounded}; use borrow::Borrow; use vec_deque::VecDeque; +use format_helpers::*; use self::Continuation::{Continue, Finished}; use self::StackOp::*; @@ -930,6 +931,16 @@ impl Debug for BTreeMap { } } +impl_map_fmt! { + BTreeMap, + Octal => map_fmt_octal, + Binary => map_fmt_binary, + LowerHex => map_fmt_lower_hex, + UpperHex => map_fmt_upper_hex, + LowerExp => map_fmt_lower_exp, + UpperExp => map_fmt_upper_exp +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K: Ord, Q: ?Sized, V> Index<&'a Q> for BTreeMap where K: Borrow, Q: Ord diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index fc346151e0b4b..67574802a46a2 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -23,6 +23,8 @@ use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use Bound; +use format_helpers::*; + // FIXME(conventions): implement bounded iterators /// A set based on a B-Tree. @@ -626,6 +628,16 @@ impl Debug for BTreeSet { } } +impl_set_fmt! { + BTreeSet, + Octal => seq_fmt_octal, + Binary => seq_fmt_binary, + LowerHex => seq_fmt_lower_hex, + UpperHex => seq_fmt_upper_hex, + LowerExp => seq_fmt_lower_exp, + UpperExp => seq_fmt_upper_exp +} + impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { Iter { iter: self.iter.clone() } } } diff --git a/src/libcollections/format_helpers.rs b/src/libcollections/format_helpers.rs new file mode 100644 index 0000000000000..31a808f147694 --- /dev/null +++ b/src/libcollections/format_helpers.rs @@ -0,0 +1,175 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::fmt::{self, Formatter}; +use core::iter::{Iterator}; +use core::result::Result; + +pub fn seq_fmt_debug(s: I, f: &mut Formatter) -> fmt::Result + where I::Item: fmt::Debug +{ + for (i, e) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:?}", e)); + } + + Result::Ok(()) +} + +pub fn seq_fmt_octal(s: I, f: &mut Formatter) -> fmt::Result + where I::Item: fmt::Octal +{ + for (i, e) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:o}", e)); + } + + Result::Ok(()) +} + +pub fn seq_fmt_binary(s: I, f: &mut Formatter) -> fmt::Result + where I::Item: fmt::Binary +{ + for (i, e) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:b}", e)); + } + + Result::Ok(()) +} + +pub fn seq_fmt_upper_hex(s: I, f: &mut Formatter) -> fmt::Result + where I::Item: fmt::UpperHex +{ + for (i, e) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:X}", e)); + } + + Result::Ok(()) +} + +pub fn seq_fmt_lower_hex(s: I, f: &mut Formatter) -> fmt::Result + where I::Item: fmt::LowerHex +{ + for (i, e) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:x}", e)); + } + + Result::Ok(()) +} + +pub fn seq_fmt_upper_exp(s: I, f: &mut Formatter) -> fmt::Result + where I::Item: fmt::UpperExp +{ + for (i, e) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:E}", e)); + } + + Result::Ok(()) +} + +pub fn seq_fmt_lower_exp(s: I, f: &mut Formatter) -> fmt::Result + where I::Item: fmt::LowerExp +{ + for (i, e) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:e}", e)); + } + + Result::Ok(()) +} + +pub fn map_fmt_debug>(s: I, f: &mut Formatter) -> fmt::Result + where K: fmt::Debug, + V: fmt::Debug +{ + for (i, (k, v)) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:?}: {:?}", k, v)); + } + + Result::Ok(()) +} + +pub fn map_fmt_octal>(s: I, f: &mut Formatter) -> fmt::Result + where K: fmt::Octal, + V: fmt::Octal +{ + for (i, (k, v)) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:o}: {:o}", k, v)); + } + + Result::Ok(()) +} + +pub fn map_fmt_binary>(s: I, f: &mut Formatter) -> fmt::Result + where K: fmt::Binary, + V: fmt::Binary +{ + for (i, (k, v)) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:b}: {:b}", k, v)); + } + + Result::Ok(()) +} + +pub fn map_fmt_upper_hex>(s: I, f: &mut Formatter) -> fmt::Result + where K: fmt::UpperHex, + V: fmt::UpperHex +{ + for (i, (k, v)) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:X}: {:X}", k, v)); + } + + Result::Ok(()) +} + +pub fn map_fmt_lower_hex>(s: I, f: &mut Formatter) -> fmt::Result + where K: fmt::LowerHex, + V: fmt::LowerHex +{ + for (i, (k, v)) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:x}: {:x}", k, v)); + } + + Result::Ok(()) +} + +pub fn map_fmt_upper_exp>(s: I, f: &mut Formatter) -> fmt::Result + where K: fmt::UpperExp, + V: fmt::UpperExp +{ + for (i, (k, v)) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:E}: {:E}", k, v)); + } + + Result::Ok(()) +} + +pub fn map_fmt_lower_exp>(s: I, f: &mut Formatter) -> fmt::Result + where K: fmt::LowerExp, + V: fmt::LowerExp +{ + for (i, (k, v)) in s.enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{:e}: {:e}", k, v)); + } + + Result::Ok(()) +} + diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index ecbe9369e781f..eee7f7ab45208 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -81,6 +81,7 @@ mod btree; pub mod borrow; pub mod enum_set; pub mod fmt; +mod format_helpers; pub mod linked_list; pub mod range; pub mod slice; diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index f6dc5cf7d90a0..bbcf500cd3bd7 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -31,6 +31,7 @@ use core::iter::{self, FromIterator}; use core::mem; use core::ptr; +use format_helpers::*; /// A doubly-linked list. #[stable(feature = "rust1", since = "1.0.0")] pub struct LinkedList { @@ -921,6 +922,16 @@ impl fmt::Debug for LinkedList { } } +impl_seq_fmt! { + LinkedList, + Octal => seq_fmt_octal, + Binary => seq_fmt_binary, + LowerHex => seq_fmt_lower_hex, + UpperHex => seq_fmt_upper_hex, + LowerExp => seq_fmt_lower_exp, + UpperExp => seq_fmt_upper_exp +} + #[stable(feature = "rust1", since = "1.0.0")] impl Hash for LinkedList { fn hash(&self, state: &mut H) { diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index 5f614f3649ca9..a62861bb2d130 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -75,3 +75,45 @@ macro_rules! vec { macro_rules! format { ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) } + +macro_rules! impl_seq_fmt { + ($seq:ident, $($Trait:ident => $fmt_fun:ident),+) => { + $( + impl fmt::$Trait for $seq { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "[")); + try!($fmt_fun(self.iter(), f)); + write!(f, "]") + } + } + )+ + } +} + +macro_rules! impl_set_fmt { + ($seq:ident, $($Trait:ident => $fmt_fun:ident),+) => { + $( + impl fmt::$Trait for $seq { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + try!($fmt_fun(self.iter(), f)); + write!(f, "}}") + } + } + )+ + } +} + +macro_rules! impl_map_fmt { + ($map:ident, $($Trait:ident => $fmt_fun:ident),+) => { + $( + impl fmt::$Trait for $map { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + try!($fmt_fun(self.iter(), f)); + write!(f, "}}") + } + } + )+ + }; +} diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 66bb84205e21c..786896aa50156 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -82,6 +82,8 @@ use super::range::RangeArgument; // FIXME- fix places which assume the max vector allowed has memory usize::MAX. static MAX_MEMORY_SIZE: usize = isize::MAX as usize; +use format_helpers::*; + /// A growable list type, written `Vec` but pronounced 'vector.' /// /// # Examples @@ -1653,6 +1655,16 @@ impl fmt::Debug for Vec { } } +impl_seq_fmt! { + Vec, + Octal => seq_fmt_octal, + Binary => seq_fmt_binary, + LowerHex => seq_fmt_lower_hex, + UpperHex => seq_fmt_upper_hex, + LowerExp => seq_fmt_lower_exp, + UpperExp => seq_fmt_upper_exp +} + #[stable(feature = "rust1", since = "1.0.0")] impl AsRef> for Vec { fn as_ref(&self) -> &Vec { diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index f70906f84b869..94d8ffde645df 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -32,6 +32,8 @@ use core::hash::{Hash, Hasher}; use core::cmp; use alloc::heap; +use format_helpers::*; + const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 const MINIMUM_CAPACITY: usize = 1; // 2 - 1 @@ -1791,18 +1793,15 @@ impl Extend for VecDeque { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for VecDeque { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "[")); - - for (i, e) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *e)); - } - - write!(f, "]") - } +impl_seq_fmt! { + VecDeque, + Debug => seq_fmt_debug, + Octal => seq_fmt_octal, + Binary => seq_fmt_binary, + LowerHex => seq_fmt_lower_hex, + UpperHex => seq_fmt_upper_hex, + LowerExp => seq_fmt_lower_exp, + UpperExp => seq_fmt_upper_exp } #[cfg(test)] diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index aa0ab41b7455b..65f68ec29191d 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -27,6 +27,7 @@ use core::ops::{Index, IndexMut}; use {vec, slice}; use vec::Vec; +use format_helpers::*; /// A map optimized for small integer keys. /// @@ -742,18 +743,13 @@ impl Ord for VecMap { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for VecMap { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}: {:?}", k, *v)); - } - - write!(f, "}}") - } +impl_set_fmt! { + VecMap, + Debug => map_fmt_debug, + Octal => map_fmt_octal, + Binary => map_fmt_binary, + LowerHex => map_fmt_lower_hex, + UpperHex => map_fmt_upper_hex } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcollectionstest/fmt.rs b/src/libcollectionstest/fmt.rs index 70e21c65a1806..bccaf28d7b30d 100644 --- a/src/libcollectionstest/fmt.rs +++ b/src/libcollectionstest/fmt.rs @@ -9,9 +9,100 @@ // except according to those terms. use std::fmt; +use std::collections::{BTreeMap, BTreeSet, LinkedList, VecDeque, VecMap}; + #[test] fn test_format() { let s = fmt::format(format_args!("Hello, {}!", "world")); assert_eq!(s, "Hello, world!"); + + let u32_array = [10u32, 20, 64, 255, 0xffffffff]; + assert_eq!(format!("{:?}", u32_array), "[10, 20, 64, 255, 4294967295]"); + assert_eq!(format!("{:o}", u32_array), "[12, 24, 100, 377, 37777777777]"); + assert_eq!(format!("{:b}", u32_array), + "[1010, 10100, 1000000, 11111111, 11111111111111111111111111111111]"); + assert_eq!(format!("{:x}", u32_array), "[a, 14, 40, ff, ffffffff]"); + assert_eq!(format!("{:X}", u32_array), "[A, 14, 40, FF, FFFFFFFF]"); + + let f32_array = [10f32, 20.0 , 64.0, 255.0]; + assert_eq!(format!("{:?}", f32_array), "[10, 20, 64, 255]"); + assert_eq!(format!("{:e}", f32_array), "[1e1, 2e1, 6.4e1, 2.55e2]"); + assert_eq!(format!("{:E}", f32_array), "[1E1, 2E1, 6.4E1, 2.55E2]"); + + let u32_vec = vec![10u32, 20, 64, 255, 0xffffffff]; + assert_eq!(format!("{:?}", u32_vec), "[10, 20, 64, 255, 4294967295]"); + assert_eq!(format!("{:o}", u32_vec), "[12, 24, 100, 377, 37777777777]"); + assert_eq!(format!("{:b}", u32_vec), + "[1010, 10100, 1000000, 11111111, 11111111111111111111111111111111]"); + assert_eq!(format!("{:x}", u32_vec), "[a, 14, 40, ff, ffffffff]"); + assert_eq!(format!("{:X}", u32_vec), "[A, 14, 40, FF, FFFFFFFF]"); + + let f32_vec = vec![10f32, 20.0 , 64.0, 255.0]; + assert_eq!(format!("{:?}", f32_vec), "[10, 20, 64, 255]"); + assert_eq!(format!("{:e}", f32_vec), "[1e1, 2e1, 6.4e1, 2.55e2]"); + assert_eq!(format!("{:E}", f32_vec), "[1E1, 2E1, 6.4E1, 2.55E2]"); + + let u32_linked_list: LinkedList<_> = u32_vec.into_iter().collect(); + assert_eq!(format!("{:?}", u32_linked_list), "[10, 20, 64, 255, 4294967295]"); + assert_eq!(format!("{:o}", u32_linked_list), "[12, 24, 100, 377, 37777777777]"); + assert_eq!(format!("{:b}", u32_linked_list), + "[1010, 10100, 1000000, 11111111, 11111111111111111111111111111111]"); + assert_eq!(format!("{:x}", u32_linked_list), "[a, 14, 40, ff, ffffffff]"); + assert_eq!(format!("{:X}", u32_linked_list), "[A, 14, 40, FF, FFFFFFFF]"); + + let f32_linked_list: LinkedList<_> = f32_vec.into_iter().collect(); + assert_eq!(format!("{:?}", f32_linked_list), "[10, 20, 64, 255]"); + assert_eq!(format!("{:e}", f32_linked_list), "[1e1, 2e1, 6.4e1, 2.55e2]"); + assert_eq!(format!("{:E}", f32_linked_list), "[1E1, 2E1, 6.4E1, 2.55E2]"); + + let mut u32_vec_map: VecMap = VecMap::new(); + for (i, x) in u32_linked_list.into_iter().enumerate() { + u32_vec_map.insert(i, x); + } + + assert_eq!(format!("{:?}", u32_vec_map), "{0: 10, 1: 20, 2: 64, 3: 255, 4: 4294967295}"); + assert_eq!(format!("{:o}", u32_vec_map), "{0: 12, 1: 24, 2: 100, 3: 377, 4: 37777777777}"); + assert_eq!(format!("{:b}", u32_vec_map), + "{0: 1010, 1: 10100, 2: 1000000, 3: 11111111, 4: 11111111111111111111111111111111}"); + assert_eq!(format!("{:x}", u32_vec_map), "{0: a, 1: 14, 2: 40, 3: ff, 4: ffffffff}"); + assert_eq!(format!("{:X}", u32_vec_map), "{0: A, 1: 14, 2: 40, 3: FF, 4: FFFFFFFF}"); + + let u32_ring_buf: VecDeque<_> = u32_vec_map.values().collect(); + assert_eq!(format!("{:?}", u32_ring_buf), "[10, 20, 64, 255, 4294967295]"); + assert_eq!(format!("{:o}", u32_ring_buf), "[12, 24, 100, 377, 37777777777]"); + assert_eq!(format!("{:b}", u32_ring_buf), + "[1010, 10100, 1000000, 11111111, 11111111111111111111111111111111]"); + assert_eq!(format!("{:x}", u32_ring_buf), "[a, 14, 40, ff, ffffffff]"); + assert_eq!(format!("{:X}", u32_ring_buf), "[A, 14, 40, FF, FFFFFFFF]"); + + let f32_ring_buf: VecDeque<_> = f32_linked_list.into_iter().collect(); + assert_eq!(format!("{:?}", f32_ring_buf), "[10, 20, 64, 255]"); + assert_eq!(format!("{:e}", f32_ring_buf), "[1e1, 2e1, 6.4e1, 2.55e2]"); + assert_eq!(format!("{:E}", f32_ring_buf), "[1E1, 2E1, 6.4E1, 2.55E2]"); + + let u32_btree_set: BTreeSet<_> = u32_ring_buf.into_iter().collect(); + assert_eq!(format!("{:?}", u32_btree_set), "{10, 20, 64, 255, 4294967295}"); + assert_eq!(format!("{:o}", u32_btree_set), "{12, 24, 100, 377, 37777777777}"); + assert_eq!(format!("{:b}", u32_btree_set), + "{1010, 10100, 1000000, 11111111, 11111111111111111111111111111111}"); + assert_eq!(format!("{:x}", u32_btree_set), "{a, 14, 40, ff, ffffffff}"); + assert_eq!(format!("{:X}", u32_btree_set), "{A, 14, 40, FF, FFFFFFFF}"); + + let mut u32_btree_map: BTreeMap = BTreeMap::new(); + for x in u32_btree_set { + u32_btree_map.insert(*x, *x); + }; + + assert_eq!(format!("{:?}", u32_btree_map), + "{10: 10, 20: 20, 64: 64, 255: 255, 4294967295: 4294967295}"); + assert_eq!(format!("{:o}", u32_btree_map), + "{12: 12, 24: 24, 100: 100, 377: 377, 37777777777: 37777777777}"); + assert_eq!(format!("{:b}", u32_btree_map), + "{1010: 1010, 10100: 10100, 1000000: 1000000, 11111111: 11111111, \ + 11111111111111111111111111111111: 11111111111111111111111111111111}"); + assert_eq!(format!("{:x}", u32_btree_map), + "{a: a, 14: 14, 40: 40, ff: ff, ffffffff: ffffffff}"); + assert_eq!(format!("{:X}", u32_btree_map), + "{A: A, 14: 14, 40: 40, FF: FF, FFFFFFFF: FFFFFFFF}"); } diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 91301ee558ca5..99018000710ec 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -38,6 +38,18 @@ pub trait FixedSizeArray { fn as_mut_slice(&mut self) -> &mut [T]; } +macro_rules! fmt_array { + ($N:expr, $($Trait:ident),*) => { + $( + impl fmt::$Trait for [T; $N] { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::$Trait::fmt(&&self[..], f) + } + } + )* + } +} + // macro for implementing n-ary tuple functions and operations macro_rules! array_impls { ($($N:expr)+) => { @@ -86,12 +98,7 @@ macro_rules! array_impls { } } - #[stable(feature = "rust1", since = "1.0.0")] - impl fmt::Debug for [T; $N] { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&&self[..], f) - } - } + fmt_array! { $N, Debug, Octal, Binary, UpperHex, LowerHex, UpperExp, LowerExp } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> IntoIterator for &'a [T; $N] { diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index a87f6619fe877..023ff9e38a633 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1124,6 +1124,33 @@ impl Debug for [T] { } } +macro_rules! fmt_slice { + ($($Trait:ident => $fmt_char:expr),*) => { + $( + impl $Trait for [T] { + fn fmt(&self, f: &mut Formatter) -> Result { + try!(write!(f, "[")); + for (i, x) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, $fmt_char, *x)); + } + write!(f, "]") + } + } + )* + } +} + +fmt_slice! { + Octal => "{:o}", + Binary => "{:b}", + UpperHex => "{:X}", + LowerHex => "{:x}", + UpperExp => "{:E}", + LowerExp => "{:e}" +} + + #[stable(feature = "rust1", since = "1.0.0")] impl Debug for () { fn fmt(&self, f: &mut Formatter) -> Result {