From 2d26b3bc3f8a22643f5745722c9714436f1ac924 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 19 May 2014 11:32:09 -0700 Subject: [PATCH] core: Rename `container` mod to `collections`. Closes #12543 Also renames the `Container` trait to `Collection`. [breaking-change] --- src/libcollections/bitv.rs | 2 +- src/libcollections/deque.rs | 4 +- src/libcollections/dlist.rs | 2 +- src/libcollections/hashmap.rs | 7 +- src/libcollections/lru_cache.rs | 3 +- src/libcollections/priority_queue.rs | 2 +- src/libcollections/ringbuf.rs | 2 +- src/libcollections/smallintmap.rs | 2 +- src/libcollections/treemap.rs | 4 +- src/libcollections/trie.rs | 4 +- src/libcore/{container.rs => collections.rs} | 10 +- src/libcore/fmt/float.rs | 2 +- src/libcore/fmt/mod.rs | 2 +- src/libcore/fmt/num.rs | 2 +- src/libcore/lib.rs | 2 +- src/libcore/prelude.rs | 2 +- src/libcore/should_not_exist.rs | 2 +- src/libcore/slice.rs | 10 +- src/libcore/str.rs | 10 +- src/libregex/re.rs | 2 +- src/librustc/middle/trans/adt.rs | 1 - src/libstd/ascii.rs | 2 +- src/libstd/c_str.rs | 4 +- src/libstd/c_vec.rs | 4 +- src/libstd/comm/sync.rs | 2 +- src/libstd/fmt/mod.rs | 1402 +++++++++++++++++ src/libstd/hash/mod.rs | 2 +- src/libstd/hash/sip.rs | 2 +- src/libstd/io/buffered.rs | 2 +- src/libstd/io/comm_adapters.rs | 2 +- src/libstd/io/extensions.rs | 4 +- src/libstd/io/fs.rs | 2 +- src/libstd/io/mem.rs | 2 +- src/libstd/io/mod.rs | 2 +- src/libstd/io/net/ip.rs | 2 +- src/libstd/lib.rs | 2 +- src/libstd/num/strconv.rs | 2 +- src/libstd/os.rs | 2 +- src/libstd/path/mod.rs | 2 +- src/libstd/path/posix.rs | 2 +- src/libstd/path/windows.rs | 2 +- src/libstd/prelude.rs | 2 +- src/libstd/repr.rs | 2 +- src/libstd/rt/backtrace.rs | 4 +- src/libstd/rt/util.rs | 2 +- src/libstd/slice.rs | 2 +- src/libstd/str.rs | 6 +- src/libstd/strbuf.rs | 6 +- src/libstd/vec.rs | 4 +- src/libsyntax/owned_slice.rs | 2 +- src/libsyntax/util/small_vector.rs | 2 +- src/test/compile-fail/map-types.rs | 4 +- .../class-impl-very-parameterized-trait.rs | 2 +- src/test/run-pass/send_str_hashmap.rs | 2 +- src/test/run-pass/send_str_treemap.rs | 2 +- 55 files changed, 1481 insertions(+), 84 deletions(-) rename src/libcore/{container.rs => collections.rs} (95%) create mode 100644 src/libstd/fmt/mod.rs diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs index e2934efa43b65..6f86402c6f77a 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bitv.rs @@ -833,7 +833,7 @@ impl cmp::Eq for BitvSet { fn ne(&self, other: &BitvSet) -> bool { !self.eq(other) } } -impl Container for BitvSet { +impl Collection for BitvSet { #[inline] fn len(&self) -> uint { self.size } } diff --git a/src/libcollections/deque.rs b/src/libcollections/deque.rs index e031b07f87296..72baad7aeac20 100644 --- a/src/libcollections/deque.rs +++ b/src/libcollections/deque.rs @@ -10,8 +10,6 @@ //! Container traits for collections -use std::container::Mutable; - /// A double-ended sequence that allows querying, insertion and deletion at both ends. pub trait Deque : Mutable { /// Provide a reference to the front element, or None if the sequence is empty @@ -43,7 +41,7 @@ pub trait Deque : Mutable { pub mod bench { extern crate test; use self::test::Bencher; - use std::container::MutableMap; + use std::collections::MutableMap; use rand; use rand::Rng; diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 58ced1beeed60..55dc9ad2f7a64 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -122,7 +122,7 @@ fn link_with_prev(mut next: Box>, prev: Rawlink>) Some(next) } -impl Container for DList { +impl Collection for DList { /// O(1) #[inline] fn is_empty(&self) -> bool { diff --git a/src/libcollections/hashmap.rs b/src/libcollections/hashmap.rs index 4259f458e0064..ee17a00773294 100644 --- a/src/libcollections/hashmap.rs +++ b/src/libcollections/hashmap.rs @@ -10,7 +10,6 @@ //! Unordered containers, implemented as hash-tables (`HashSet` and `HashMap` types) -use std::container::{Container, Mutable, Map, MutableMap, Set, MutableSet}; use std::clone::Clone; use std::cmp::{Eq, TotalEq, Equiv, max}; use std::default::Default; @@ -925,7 +924,7 @@ impl, V, S, H: Hasher> HashMap { } } -impl, V, S, H: Hasher> Container for HashMap { +impl, V, S, H: Hasher> Collection for HashMap { /// Return the number of elements in the map fn len(&self) -> uint { self.table.size() } } @@ -1494,7 +1493,7 @@ impl, S, H: Hasher> Eq for HashSet { } } -impl, S, H: Hasher> Container for HashSet { +impl, S, H: Hasher> Collection for HashSet { fn len(&self) -> uint { self.map.len() } } @@ -2079,7 +2078,7 @@ mod test_map { #[cfg(test)] mod test_set { use super::HashSet; - use std::container::Container; + use std::collections::Collection; use std::slice::ImmutableEqVector; #[test] diff --git a/src/libcollections/lru_cache.rs b/src/libcollections/lru_cache.rs index 8fdc0e095bf41..344b199850fb7 100644 --- a/src/libcollections/lru_cache.rs +++ b/src/libcollections/lru_cache.rs @@ -37,7 +37,6 @@ //! assert!(cache.get(&2).is_none()); //! ``` -use std::container::Container; use std::hash::Hash; use std::fmt; use std::mem; @@ -222,7 +221,7 @@ impl fmt::Show for LruCache { } } -impl Container for LruCache { +impl Collection for LruCache { /// Return the number of key-value pairs in the cache. fn len(&self) -> uint { self.map.len() diff --git a/src/libcollections/priority_queue.rs b/src/libcollections/priority_queue.rs index 4a0daf529de88..62b4f63d6315b 100644 --- a/src/libcollections/priority_queue.rs +++ b/src/libcollections/priority_queue.rs @@ -22,7 +22,7 @@ pub struct PriorityQueue { data: Vec, } -impl Container for PriorityQueue { +impl Collection for PriorityQueue { /// Returns the length of the queue fn len(&self) -> uint { self.data.len() } } diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs index 12e4fa8b51f24..425f0f17bddd4 100644 --- a/src/libcollections/ringbuf.rs +++ b/src/libcollections/ringbuf.rs @@ -29,7 +29,7 @@ pub struct RingBuf { elts: Vec> } -impl Container for RingBuf { +impl Collection for RingBuf { /// Return the number of elements in the RingBuf fn len(&self) -> uint { self.nelts } } diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/smallintmap.rs index fb02ddd6224c4..af8b629b07c72 100644 --- a/src/libcollections/smallintmap.rs +++ b/src/libcollections/smallintmap.rs @@ -24,7 +24,7 @@ pub struct SmallIntMap { v: Vec>, } -impl Container for SmallIntMap { +impl Collection for SmallIntMap { /// Return the number of elements in the map fn len(&self) -> uint { self.v.iter().count(|elt| elt.is_some()) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index bb4ca36709c25..4413cd7eec3df 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -67,7 +67,7 @@ impl Ord for TreeMap { fn lt(&self, other: &TreeMap) -> bool { lt(self, other) } } -impl Container for TreeMap { +impl Collection for TreeMap { fn len(&self) -> uint { self.length } } @@ -547,7 +547,7 @@ impl Ord for TreeSet { fn lt(&self, other: &TreeSet) -> bool { self.map < other.map } } -impl Container for TreeSet { +impl Collection for TreeSet { #[inline] fn len(&self) -> uint { self.map.len() } } diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index 9d64b3c2394b0..fe95db21f8715 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -34,7 +34,7 @@ pub struct TrieMap { length: uint } -impl Container for TrieMap { +impl Collection for TrieMap { /// Return the number of elements in the map #[inline] fn len(&self) -> uint { self.length } @@ -281,7 +281,7 @@ pub struct TrieSet { map: TrieMap<()> } -impl Container for TrieSet { +impl Collection for TrieSet { /// Return the number of elements in the set #[inline] fn len(&self) -> uint { self.map.len() } diff --git a/src/libcore/container.rs b/src/libcore/collections.rs similarity index 95% rename from src/libcore/container.rs rename to src/libcore/collections.rs index e8ee3792dcf2c..8ebc7c2f7fe2a 100644 --- a/src/libcore/container.rs +++ b/src/libcore/collections.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Traits for generic containers (including `Map` and `Set`) +//! Traits for generic collections (including `Map` and `Set`) use option::Option; /// A trait to represent the abstract idea of a container. The only concrete /// knowledge known is the number of elements contained within. -pub trait Container { +pub trait Collection { /// Return the number of elements in the container fn len(&self) -> uint; @@ -26,14 +26,14 @@ pub trait Container { } /// A trait to represent mutable containers -pub trait Mutable: Container { +pub trait Mutable: Collection { /// Clear the container, removing all values. fn clear(&mut self); } /// A map is a key-value store where values may be looked up by their keys. This /// trait provides basic operations to operate on these stores. -pub trait Map: Container { +pub trait Map: Collection { /// Return a reference to the value corresponding to the key fn find<'a>(&'a self, key: &K) -> Option<&'a V>; @@ -76,7 +76,7 @@ pub trait MutableMap: Map + Mutable { /// A set is a group of objects which are each distinct from one another. This /// trait represents actions which can be performed on sets to iterate over /// them. -pub trait Set: Container { +pub trait Set: Collection { /// Return true if the set contains a value fn contains(&self, value: &T) -> bool; diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index e5fb148aded34..f326195be1607 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -11,7 +11,7 @@ #![allow(missing_doc)] use char; -use container::Container; +use collections::Collection; use fmt; use iter::{Iterator, range, DoubleEndedIterator}; use num::{Float, FPNaN, FPInfinite, ToPrimitive, Primitive}; diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index af492dc295aca..7635855e2b334 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -15,7 +15,7 @@ use any; use cell::Cell; use char::Char; -use container::Container; +use collections::Collection; use iter::{Iterator, range}; use kinds::Copy; use mem; diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index d9a3271378125..d6fb7988caaff 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -14,7 +14,7 @@ #![allow(unsigned_negate)] -use container::Container; +use collections::Collection; use fmt; use iter::{Iterator, DoubleEndedIterator}; use num::{Int, cast, zero}; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index ffb9b676e7d47..b83fa5163e7bc 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -108,7 +108,7 @@ pub mod ptr; #[cfg(not(test))] pub mod cmp; pub mod clone; pub mod default; -pub mod container; +pub mod collections; /* Core types and methods on primitives */ diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index a8e78e52b12f8..d354f3ae9c531 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -46,7 +46,7 @@ pub use mem::drop; pub use char::Char; pub use clone::Clone; pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv}; -pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet}; +pub use collections::{Collection, Mutable, Map, MutableMap, Set, MutableSet}; pub use iter::{FromIterator, Extendable}; pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator}; pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize}; diff --git a/src/libcore/should_not_exist.rs b/src/libcore/should_not_exist.rs index ccca52c573d21..b8f3d37a4c576 100644 --- a/src/libcore/should_not_exist.rs +++ b/src/libcore/should_not_exist.rs @@ -26,7 +26,7 @@ use char::Char; use clone::Clone; -use container::Container; +use collections::Collection; use default::Default; use finally::try_finally; use intrinsics; diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 755c6738b4a62..03bfb8f35f7e3 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -14,7 +14,7 @@ use mem::transmute; use clone::Clone; -use container::Container; +use collections::Collection; use cmp::{Eq, TotalOrd, Ordering, Less, Equal, Greater}; use cmp; use default::Default; @@ -251,7 +251,7 @@ pub mod traits { use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Equiv}; use iter::{order, Iterator}; - use container::Container; + use collections::Collection; impl<'a,T:Eq> Eq for &'a [T] { fn eq(&self, other: & &'a [T]) -> bool { @@ -345,7 +345,7 @@ impl Vector for ~[T] { fn as_slice<'a>(&'a self) -> &'a [T] { let v: &'a [T] = *self; v } } -impl<'a, T> Container for &'a [T] { +impl<'a, T> Collection for &'a [T] { /// Returns the length of a vector #[inline] fn len(&self) -> uint { @@ -353,7 +353,7 @@ impl<'a, T> Container for &'a [T] { } } -impl Container for ~[T] { +impl Collection for ~[T] { /// Returns the length of a vector #[inline] fn len(&self) -> uint { @@ -1235,7 +1235,7 @@ pub mod raw { /// Operations on `[u8]`. pub mod bytes { - use container::Container; + use collections::Collection; use ptr; use slice::MutableVector; diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 0d820836377d3..809149f49de51 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -17,7 +17,7 @@ use char; use clone::Clone; use cmp; use cmp::{Eq, TotalEq}; -use container::Container; +use collections::Collection; use default::Default; use iter::{Filter, Map, Iterator}; use iter::{Rev, DoubleEndedIterator, ExactSize}; @@ -890,7 +890,7 @@ static TAG_CONT_U8: u8 = 128u8; /// Unsafe operations pub mod raw { use mem; - use container::Container; + use collections::Collection; use iter::Iterator; use ptr::RawPtr; use raw::Slice; @@ -955,7 +955,7 @@ Section: Trait implementations #[cfg(not(test))] #[allow(missing_doc)] pub mod traits { - use container::Container; + use collections::Collection; use cmp::{TotalOrd, Ordering, Less, Equal, Greater, Eq, Ord, Equiv, TotalEq}; use iter::Iterator; use option::{Some, None}; @@ -1041,14 +1041,14 @@ impl<'a> Str for ~str { fn as_slice<'a>(&'a self) -> &'a str { let s: &'a str = *self; s } } -impl<'a> Container for &'a str { +impl<'a> Collection for &'a str { #[inline] fn len(&self) -> uint { self.repr().len } } -impl Container for ~str { +impl Collection for ~str { #[inline] fn len(&self) -> uint { self.as_slice().len() } } diff --git a/src/libregex/re.rs b/src/libregex/re.rs index 899c54d601bdb..7f2be292d9c72 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -724,7 +724,7 @@ impl<'t> Captures<'t> { } } -impl<'t> Container for Captures<'t> { +impl<'t> Collection for Captures<'t> { /// Returns the number of captured groups. #[inline] fn len(&self) -> uint { diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 9cea6d0249cc4..64625909d2063 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -45,7 +45,6 @@ #![allow(unsigned_negate)] -use std::container::Map; use libc::c_ulonglong; use std::num::{Bitwise}; use std::rc::Rc; diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index e087b3d177499..496e1e50a836f 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -10,7 +10,7 @@ //! Operations on ASCII strings and characters -use container::Container; +use collections::Collection; use fmt; use iter::Iterator; use mem; diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 0c529ee4d963e..ebf7975101cc9 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -67,7 +67,7 @@ fn main() { use clone::Clone; use cmp::Eq; -use container::Container; +use collections::Collection; use iter::{Iterator, range}; use kinds::marker; use libc; @@ -236,7 +236,7 @@ impl Drop for CString { } } -impl Container for CString { +impl Collection for CString { /// Return the number of bytes in the CString (not including the NUL terminator). /// /// # Failure diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs index 817b54fb692f2..e8a158ad230aa 100644 --- a/src/libstd/c_vec.rs +++ b/src/libstd/c_vec.rs @@ -33,7 +33,7 @@ //! handled correctly, i.e. that allocated memory is eventually freed //! if necessary. -use container::Container; +use collections::Collection; use kinds::Send; use mem; use ops::Drop; @@ -149,7 +149,7 @@ impl CVec { } } -impl Container for CVec { +impl Collection for CVec { fn len(&self) -> uint { self.len } } diff --git a/src/libstd/comm/sync.rs b/src/libstd/comm/sync.rs index 819e885526cbf..d94780b9ec87e 100644 --- a/src/libstd/comm/sync.rs +++ b/src/libstd/comm/sync.rs @@ -33,7 +33,7 @@ /// of a synchronous channel. There are a few branches for the unbuffered case, /// but they're mostly just relevant to blocking senders. -use container::Container; +use collections::Collection; use iter::Iterator; use kinds::Send; use mem; diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs new file mode 100644 index 0000000000000..261531b1fb104 --- /dev/null +++ b/src/libstd/fmt/mod.rs @@ -0,0 +1,1402 @@ +// Copyright 2013-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. + +/*! + +Utilities for formatting and printing strings + +This module contains the runtime support for the `format!` syntax extension. +This macro is implemented in the compiler to emit calls to this module in order +to format arguments at runtime into strings and streams. + +The functions contained in this module should not normally be used in everyday +use cases of `format!`. The assumptions made by these functions are unsafe for +all inputs, and the compiler performs a large amount of validation on the +arguments to `format!` in order to ensure safety at runtime. While it is +possible to call these functions directly, it is not recommended to do so in the +general case. + +## Usage + +The `format!` macro is intended to be familiar to those coming from C's +printf/fprintf functions or Python's `str.format` function. In its current +revision, the `format!` macro returns a `~str` type which is the result of the +formatting. In the future it will also be able to pass in a stream to format +arguments directly while performing minimal allocations. + +Some examples of the `format!` extension are: + +```rust +format!("Hello"); // => "Hello".to_owned() +format!("Hello, {:s}!", "world"); // => "Hello, world!".to_owned() +format!("The number is {:d}", 1); // => "The number is 1".to_owned() +format!("{:?}", ~[3, 4]); // => "~[3, 4]".to_owned() +format!("{value}", value=4); // => "4".to_owned() +format!("{} {}", 1, 2); // => "1 2".to_owned() +``` + +From these, you can see that the first argument is a format string. It is +required by the compiler for this to be a string literal; it cannot be a +variable passed in (in order to perform validity checking). The compiler will +then parse the format string and determine if the list of arguments provided is +suitable to pass to this format string. + +### Positional parameters + +Each formatting argument is allowed to specify which value argument it's +referencing, and if omitted it is assumed to be "the next argument". For +example, the format string `{} {} {}` would take three parameters, and they +would be formatted in the same order as they're given. The format string +`{2} {1} {0}`, however, would format arguments in reverse order. + +Things can get a little tricky once you start intermingling the two types of +positional specifiers. The "next argument" specifier can be thought of as an +iterator over the argument. Each time a "next argument" specifier is seen, the +iterator advances. This leads to behavior like this: + +```rust +format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2".to_owned() +``` + +The internal iterator over the argument has not been advanced by the time the +first `{}` is seen, so it prints the first argument. Then upon reaching the +second `{}`, the iterator has advanced forward to the second argument. +Essentially, parameters which explicitly name their argument do not affect +parameters which do not name an argument in terms of positional specifiers. + +A format string is required to use all of its arguments, otherwise it is a +compile-time error. You may refer to the same argument more than once in the +format string, although it must always be referred to with the same type. + +### Named parameters + +Rust itself does not have a Python-like equivalent of named parameters to a +function, but the `format!` macro is a syntax extension which allows it to +leverage named parameters. Named parameters are listed at the end of the +argument list and have the syntax: + +```notrust +identifier '=' expression +``` + +For example, the following `format!` expressions all use named argument: + +```rust +format!("{argument}", argument = "test"); // => "test".to_owned() +format!("{name} {}", 1, name = 2); // => "2 1".to_owned() +format!("{a:s} {c:d} {b:?}", a="a", b=(), c=3); // => "a 3 ()".to_owned() +``` + +It is illegal to put positional parameters (those without names) after arguments +which have names. Like positional parameters, it is illegal to provided named +parameters that are unused by the format string. + +### Argument types + +Each argument's type is dictated by the format string. It is a requirement that +every argument is only ever referred to by one type. When specifying the format +of an argument, however, a string like `{}` indicates no type. This is allowed, +and if all references to one argument do not provide a type, then the format `?` +is used (the type's rust-representation is printed). For example, this is an +invalid format string: + +```notrust +{0:d} {0:s} +``` + +Because the first argument is both referred to as an integer as well as a +string. + +Because formatting is done via traits, there is no requirement that the +`d` format actually takes an `int`, but rather it simply requires a type which +ascribes to the `Signed` formatting trait. There are various parameters which do +require a particular type, however. Namely if the syntax `{:.*s}` is used, then +the number of characters to print from the string precedes the actual string and +must have the type `uint`. Although a `uint` can be printed with `{:u}`, it is +illegal to reference an argument as such. For example, this is another invalid +format string: + +```notrust +{:.*s} {0:u} +``` + +### Formatting traits + +When requesting that an argument be formatted with a particular type, you are +actually requesting that an argument ascribes to a particular trait. This allows +multiple actual types to be formatted via `{:d}` (like `i8` as well as `int`). +The current mapping of types to traits is: + +* `?` ⇒ `Poly` +* `d` ⇒ `Signed` +* `i` ⇒ `Signed` +* `u` ⇒ `Unsigned` +* `b` ⇒ `Bool` +* `c` ⇒ `Char` +* `o` ⇒ `Octal` +* `x` ⇒ `LowerHex` +* `X` ⇒ `UpperHex` +* `s` ⇒ `String` +* `p` ⇒ `Pointer` +* `t` ⇒ `Binary` +* `f` ⇒ `Float` +* `e` ⇒ `LowerExp` +* `E` ⇒ `UpperExp` +* *nothing* ⇒ `Show` + +What this means is that any type of argument which implements the +`std::fmt::Binary` trait can then be formatted with `{:t}`. Implementations are +provided for these traits for a number of primitive types by the standard +library as well. If no format is specified (as in `{}` or `{:6}`), then the +format trait used is the `Show` trait. This is one of the more commonly +implemented traits when formatting a custom type. + +When implementing a format trait for your own type, you will have to implement a +method of the signature: + +```rust +# use std; +# mod fmt { pub type Result = (); } +# struct T; +# trait SomeName { +fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result; +# } +``` + +Your type will be passed as `self` by-reference, and then the function should +emit output into the `f.buf` stream. It is up to each format trait +implementation to correctly adhere to the requested formatting parameters. The +values of these parameters will be listed in the fields of the `Formatter` +struct. In order to help with this, the `Formatter` struct also provides some +helper methods. + +Additionally, the return value of this function is `fmt::Result` which is a +typedef to `Result<(), IoError>` (also known as `IoError<()>`). Formatting +implementations should ensure that they return errors from `write!` correctly +(propagating errors upward). + +An example of implementing the formatting traits would look +like: + +```rust +use std::fmt; +use std::f64; + +struct Vector2D { + x: int, + y: int, +} + +impl fmt::Show for Vector2D { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // The `f.buf` value is of the type `&mut io::Writer`, which is what the + // write! macro is expecting. Note that this formatting ignores the + // various flags provided to format strings. + write!(f.buf, "({}, {})", self.x, self.y) + } +} + +// Different traits allow different forms of output of a type. The meaning of +// this format is to print the magnitude of a vector. +impl fmt::Binary for Vector2D { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let magnitude = (self.x * self.x + self.y * self.y) as f64; + let magnitude = magnitude.sqrt(); + + // Respect the formatting flags by using the helper method + // `pad_integral` on the Formatter object. See the method documentation + // for details, and the function `pad` can be used to pad strings. + let decimals = f.precision.unwrap_or(3); + let string = f64::to_str_exact(magnitude, decimals); + f.pad_integral(true, "", string.as_bytes()) + } +} + +fn main() { + let myvector = Vector2D { x: 3, y: 4 }; + + println!("{}", myvector); // => "(3, 4)" + println!("{:10.3t}", myvector); // => " 5.000" +} +``` + +### Related macros + +There are a number of related macros in the `format!` family. The ones that are +currently implemented are: + +```ignore +format! // described above +write! // first argument is a &mut io::Writer, the destination +writeln! // same as write but appends a newline +print! // the format string is printed to the standard output +println! // same as print but appends a newline +format_args! // described below. +``` + + +#### `write!` + +This and `writeln` are two macros which are used to emit the format string to a +specified stream. This is used to prevent intermediate allocations of format +strings and instead directly write the output. Under the hood, this function is +actually invoking the `write` function defined in this module. Example usage is: + +```rust +# #![allow(unused_must_use)] +use std::io; + +let mut w = io::MemWriter::new(); +write!(&mut w as &mut io::Writer, "Hello {}!", "world"); +``` + +#### `print!` + +This and `println` emit their output to stdout. Similarly to the `write!` macro, +the goal of these macros is to avoid intermediate allocations when printing +output. Example usage is: + +```rust +print!("Hello {}!", "world"); +println!("I have a newline {}", "character at the end"); +``` + +#### `format_args!` +This is a curious macro which is used to safely pass around +an opaque object describing the format string. This object +does not require any heap allocations to create, and it only +references information on the stack. Under the hood, all of +the related macros are implemented in terms of this. First +off, some example usage is: + +``` +use std::fmt; +use std::io; + +# #[allow(unused_must_use)] +# fn main() { +format_args!(fmt::format, "this returns {}", "~str"); + +let some_writer: &mut io::Writer = &mut io::stdout(); +format_args!(|args| { fmt::write(some_writer, args) }, "print with a {}", "closure"); + +fn my_fmt_fn(args: &fmt::Arguments) { + fmt::write(&mut io::stdout(), args); +} +format_args!(my_fmt_fn, "or a {} too", "function"); +# } +``` + +The first argument of the `format_args!` macro is a function (or closure) which +takes one argument of type `&fmt::Arguments`. This structure can then be +passed to the `write` and `format` functions inside this module in order to +process the format string. The goal of this macro is to even further prevent +intermediate allocations when dealing formatting strings. + +For example, a logging library could use the standard formatting syntax, but it +would internally pass around this structure until it has been determined where +output should go to. + +It is unsafe to programmatically create an instance of `fmt::Arguments` because +the operations performed when executing a format string require the compile-time +checks provided by the compiler. The `format_args!` macro is the only method of +safely creating these structures, but they can be unsafely created with the +constructor provided. + +## Internationalization + +The formatting syntax supported by the `format!` extension supports +internationalization by providing "methods" which execute various different +outputs depending on the input. The syntax and methods provided are similar to +other internationalization systems, so again nothing should seem alien. +Currently two methods are supported by this extension: "select" and "plural". + +Each method will execute one of a number of clauses, and then the value of the +clause will become what's the result of the argument's format. Inside of the +cases, nested argument strings may be provided, but all formatting arguments +must not be done through implicit positional means. All arguments inside of each +case of a method must be explicitly selected by their name or their integer +position. + +Furthermore, whenever a case is running, the special character `#` can be used +to reference the string value of the argument which was selected upon. As an +example: + +```rust +format!("{0, select, other{#}}", "hello"); // => "hello".to_owned() +``` + +This example is the equivalent of `{0:s}` essentially. + +### Select + +The select method is a switch over a `&str` parameter, and the parameter *must* +be of the type `&str`. An example of the syntax is: + +```notrust +{0, select, male{...} female{...} other{...}} +``` + +Breaking this down, the `0`-th argument is selected upon with the `select` +method, and then a number of cases follow. Each case is preceded by an +identifier which is the match-clause to execute the given arm. In this case, +there are two explicit cases, `male` and `female`. The case will be executed if +the string argument provided is an exact match to the case selected. + +The `other` case is also a required case for all `select` methods. This arm will +be executed if none of the other arms matched the word being selected over. + +### Plural + +The plural method is a switch statement over a `uint` parameter, and the +parameter *must* be a `uint`. A plural method in its full glory can be specified +as: + +```notrust +{0, plural, offset=1 =1{...} two{...} many{...} other{...}} +``` + +To break this down, the first `0` indicates that this method is selecting over +the value of the first positional parameter to the format string. Next, the +`plural` method is being executed. An optionally-supplied `offset` is then given +which indicates a number to subtract from argument `0` when matching. This is +then followed by a list of cases. + +Each case is allowed to supply a specific value to match upon with the syntax +`=N`. This case is executed if the value at argument `0` matches N exactly, +without taking the offset into account. A case may also be specified by one of +five keywords: `zero`, `one`, `two`, `few`, and `many`. These cases are matched +on after argument `0` has the offset taken into account. Currently the +definitions of `many` and `few` are hardcoded, but they are in theory defined by +the current locale. + +Finally, all `plural` methods must have an `other` case supplied which will be +executed if none of the other cases match. + +## Syntax + +The syntax for the formatting language used is drawn from other languages, so it +should not be too alien. Arguments are formatted with python-like syntax, +meaning that arguments are surrounded by `{}` instead of the C-like `%`. The +actual grammar for the formatting syntax is: + +```notrust +format_string := [ format ] * +format := '{' [ argument ] [ ':' format_spec ] [ ',' function_spec ] '}' +argument := integer | identifier + +format_spec := [[fill]align][sign]['#'][0][width]['.' precision][type] +fill := character +align := '<' | '>' +sign := '+' | '-' +width := count +precision := count | '*' +type := identifier | '' +count := parameter | integer +parameter := integer '$' + +function_spec := plural | select +select := 'select' ',' ( identifier arm ) * +plural := 'plural' ',' [ 'offset:' integer ] ( selector arm ) * +selector := '=' integer | keyword +keyword := 'zero' | 'one' | 'two' | 'few' | 'many' | 'other' +arm := '{' format_string '}' +``` + +## Formatting Parameters + +Each argument being formatted can be transformed by a number of formatting +parameters (corresponding to `format_spec` in the syntax above). These +parameters affect the string representation of what's being formatted. This +syntax draws heavily from Python's, so it may seem a bit familiar. + +### Fill/Alignment + +The fill character is provided normally in conjunction with the `width` +parameter. This indicates that if the value being formatted is smaller than +`width` some extra characters will be printed around it. The extra characters +are specified by `fill`, and the alignment can be one of two options: + +* `<` - the argument is left-aligned in `width` columns +* `>` - the argument is right-aligned in `width` columns + +### Sign/#/0 + +These can all be interpreted as flags for a particular formatter. + +* '+' - This is intended for numeric types and indicates that the sign should + always be printed. Positive signs are never printed by default, and the + negative sign is only printed by default for the `Signed` trait. This + flag indicates that the correct sign (+ or -) should always be printed. +* '-' - Currently not used +* '#' - This flag is indicates that the "alternate" form of printing should be + used. By default, this only applies to the integer formatting traits and + performs like: + * `x` - precedes the argument with a "0x" + * `X` - precedes the argument with a "0x" + * `t` - precedes the argument with a "0b" + * `o` - precedes the argument with a "0o" +* '0' - This is used to indicate for integer formats that the padding should + both be done with a `0` character as well as be sign-aware. A format + like `{:08d}` would yield `00000001` for the integer `1`, while the same + format would yield `-0000001` for the integer `-1`. Notice that the + negative version has one fewer zero than the positive version. + +### Width + +This is a parameter for the "minimum width" that the format should take up. If +the value's string does not fill up this many characters, then the padding +specified by fill/alignment will be used to take up the required space. + +The default fill/alignment for non-numerics is a space and left-aligned. The +defaults for numeric formatters is also a space but with right-alignment. If the +'0' flag is specified for numerics, then the implicit fill character is '0'. + +The value for the width can also be provided as a `uint` in the list of +parameters by using the `2$` syntax indicating that the second argument is a +`uint` specifying the width. + +### Precision + +For non-numeric types, this can be considered a "maximum width". If the +resulting string is longer than this width, then it is truncated down to this +many characters and only those are emitted. + +For integral types, this has no meaning currently. + +For floating-point types, this indicates how many digits after the decimal point +should be printed. + +## Escaping + +The literal characters `{`, `}`, or `#` may be included in a string by +preceding them with the `\` character. Since `\` is already an +escape character in Rust strings, a string literal using this escape +will look like `"\\{"`. + +*/ + +use any; +use cell::Cell; +use char::Char; +use cmp; +use collections::Collection; +use intrinsics::TypeId; +use io::MemWriter; +use io; +use iter::{Iterator, range}; +use iter; +use kinds::Copy; +use mem; +use num::Signed; +use option::{Option, Some, None}; +use owned::Box; +use repr; +use result::{Ok, Err, ResultUnwrap}; +use slice::{Vector, ImmutableVector}; +use slice; +use str::{StrSlice, StrAllocating, UTF16Item, ScalarValue, LoneSurrogate}; +use str; +use strbuf::StrBuf; + +pub use self::num::radix; +pub use self::num::Radix; +pub use self::num::RadixFmt; + +mod num; +pub mod rt; + +pub type Result = io::IoResult<()>; + +/// A struct to represent both where to emit formatting strings to and how they +/// should be formatted. A mutable version of this is passed to all formatting +/// traits. +pub struct Formatter<'a> { + /// Flags for formatting (packed version of rt::Flag) + pub flags: uint, + /// Character used as 'fill' whenever there is alignment + pub fill: char, + /// Boolean indication of whether the output should be left-aligned + pub align: rt::Alignment, + /// Optionally specified integer width that the output should be + pub width: Option, + /// Optionally specified precision for numeric types + pub precision: Option, + + /// Output buffer. + pub buf: &'a mut io::Writer, + curarg: slice::Items<'a, Argument<'a>>, + args: &'a [Argument<'a>], +} + +/// This struct represents the generic "argument" which is taken by the Xprintf +/// family of functions. It contains a function to format the given value. At +/// compile time it is ensured that the function and the value have the correct +/// types, and then this struct is used to canonicalize arguments to one type. +pub struct Argument<'a> { + formatter: extern "Rust" fn(&any::Void, &mut Formatter) -> Result, + value: &'a any::Void, +} + +impl<'a> Arguments<'a> { + /// When using the format_args!() macro, this function is used to generate the + /// Arguments structure. The compiler inserts an `unsafe` block to call this, + /// which is valid because the compiler performs all necessary validation to + /// ensure that the resulting call to format/write would be safe. + #[doc(hidden)] #[inline] + pub unsafe fn new<'a>(fmt: &'static [rt::Piece<'static>], + args: &'a [Argument<'a>]) -> Arguments<'a> { + Arguments{ fmt: mem::transmute(fmt), args: args } + } +} + +/// This structure represents a safely precompiled version of a format string +/// and its arguments. This cannot be generated at runtime because it cannot +/// safely be done so, so no constructors are given and the fields are private +/// to prevent modification. +/// +/// The `format_args!` macro will safely create an instance of this structure +/// and pass it to a user-supplied function. The macro validates the format +/// string at compile-time so usage of the `write` and `format` functions can +/// be safely performed. +pub struct Arguments<'a> { + fmt: &'a [rt::Piece<'a>], + args: &'a [Argument<'a>], +} + +impl<'a> Show for Arguments<'a> { + fn fmt(&self, fmt: &mut Formatter) -> Result { + write(fmt.buf, self) + } +} + +/// When a format is not otherwise specified, types are formatted by ascribing +/// to this trait. There is not an explicit way of selecting this trait to be +/// used for formatting, it is only if no other format is specified. +pub trait Show { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `b` character +pub trait Bool { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `c` character +pub trait Char { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `i` and `d` characters +pub trait Signed { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `u` character +pub trait Unsigned { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `o` character +pub trait Octal { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `t` character +pub trait Binary { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `x` character +pub trait LowerHex { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `X` character +pub trait UpperHex { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `s` character +pub trait String { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `?` character +pub trait Poly { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `p` character +pub trait Pointer { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `f` character +pub trait Float { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `e` character +pub trait LowerExp { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +/// Format trait for the `E` character +pub trait UpperExp { + /// Formats the value using the given formatter. + fn fmt(&self, &mut Formatter) -> Result; +} + +// FIXME #11938 - UFCS would make us able call the above methods +// directly Show::show(x, fmt). +macro_rules! uniform_fn_call_workaround { + ($( $name: ident, $trait_: ident; )*) => { + $( + #[doc(hidden)] + pub fn $name(x: &T, fmt: &mut Formatter) -> Result { + x.fmt(fmt) + } + )* + } +} +uniform_fn_call_workaround! { + secret_show, Show; + secret_bool, Bool; + secret_char, Char; + secret_signed, Signed; + secret_unsigned, Unsigned; + secret_octal, Octal; + secret_binary, Binary; + secret_lower_hex, LowerHex; + secret_upper_hex, UpperHex; + secret_string, String; + secret_poly, Poly; + secret_pointer, Pointer; + secret_float, Float; + secret_lower_exp, LowerExp; + secret_upper_exp, UpperExp; +} + +/// The `write` function takes an output stream, a precompiled format string, +/// and a list of arguments. The arguments will be formatted according to the +/// specified format string into the output stream provided. +/// +/// # Arguments +/// +/// * output - the buffer to write output to +/// * args - the precompiled arguments generated by `format_args!` +/// +/// # Example +/// +/// ```rust +/// # #![allow(unused_must_use)] +/// use std::fmt; +/// use std::io; +/// +/// let mut w = io::stdout(); +/// format_args!(|args| { fmt::write(&mut w, args); }, "Hello, {}!", "world"); +/// ``` +pub fn write(output: &mut io::Writer, args: &Arguments) -> Result { + unsafe { write_unsafe(output, args.fmt, args.args) } +} + +/// The `writeln` function takes the same arguments as `write`, except that it +/// will also write a newline (`\n`) character at the end of the format string. +pub fn writeln(output: &mut io::Writer, args: &Arguments) -> Result { + let first = unsafe { write_unsafe(output, args.fmt, args.args) }; + first.and_then(|()| output.write(['\n' as u8])) +} + +/// The `write_unsafe` function takes an output stream, a precompiled format +/// string, and a list of arguments. The arguments will be formatted according +/// to the specified format string into the output stream provided. +/// +/// See the documentation for `format` for why this function is unsafe and care +/// should be taken if calling it manually. +/// +/// Thankfully the rust compiler provides macros like `write!` and +/// `format_args!` which perform all of this validation at compile-time +/// and provide a safe interface for invoking this function. +/// +/// # Arguments +/// +/// * output - the buffer to write output to +/// * fmts - the precompiled format string to emit +/// * args - the list of arguments to the format string. These are only the +/// positional arguments (not named) +/// +/// Note that this function assumes that there are enough arguments for the +/// format string. +pub unsafe fn write_unsafe(output: &mut io::Writer, + fmt: &[rt::Piece], + args: &[Argument]) -> Result { + let mut formatter = Formatter { + flags: 0, + width: None, + precision: None, + buf: output, + align: rt::AlignUnknown, + fill: ' ', + args: args, + curarg: args.iter(), + }; + for piece in fmt.iter() { + try!(formatter.run(piece, None)); + } + Ok(()) +} + +/// The format function takes a precompiled format string and a list of +/// arguments, to return the resulting formatted string. +/// +/// # Arguments +/// +/// * args - a structure of arguments generated via the `format_args!` macro. +/// Because this structure can only be safely generated at +/// compile-time, this function is safe. +/// +/// # Example +/// +/// ```rust +/// use std::fmt; +/// +/// let s = format_args!(fmt::format, "Hello, {}!", "world"); +/// assert_eq!(s, "Hello, world!".to_owned()); +/// ``` +pub fn format(args: &Arguments) -> ~str { + unsafe { format_unsafe(args.fmt, args.args) } +} + +/// Temporary transitionary thing. +pub fn format_strbuf(args: &Arguments) -> StrBuf { + unsafe { format_unsafe_strbuf(args.fmt, args.args) } +} + +/// The unsafe version of the formatting function. +/// +/// This is currently an unsafe function because the types of all arguments +/// aren't verified by immediate callers of this function. This currently does +/// not validate that the correct types of arguments are specified for each +/// format specifier, nor that each argument itself contains the right function +/// for formatting the right type value. Because of this, the function is marked +/// as `unsafe` if this is being called manually. +/// +/// Thankfully the rust compiler provides the macro `format!` which will perform +/// all of this validation at compile-time and provides a safe interface for +/// invoking this function. +/// +/// # Arguments +/// +/// * fmts - the precompiled format string to emit. +/// * args - the list of arguments to the format string. These are only the +/// positional arguments (not named) +/// +/// Note that this function assumes that there are enough arguments for the +/// format string. +pub unsafe fn format_unsafe(fmt: &[rt::Piece], args: &[Argument]) -> ~str { + let mut output = MemWriter::new(); + write_unsafe(&mut output as &mut io::Writer, fmt, args).unwrap(); + return str::from_utf8(output.unwrap().as_slice()).unwrap().to_owned(); +} + +/// Temporary transitionary thing. +pub unsafe fn format_unsafe_strbuf(fmt: &[rt::Piece], args: &[Argument]) + -> StrBuf { + let mut output = MemWriter::new(); + write_unsafe(&mut output as &mut io::Writer, fmt, args).unwrap(); + return str::from_utf8(output.unwrap().as_slice()).unwrap().into_strbuf(); +} + +impl<'a> Formatter<'a> { + + // First up is the collection of functions used to execute a format string + // at runtime. This consumes all of the compile-time statics generated by + // the format! syntax extension. + + fn run(&mut self, piece: &rt::Piece, cur: Option<&str>) -> Result { + match *piece { + rt::String(s) => self.buf.write(s.as_bytes()), + rt::CurrentArgument(()) => self.buf.write(cur.unwrap().as_bytes()), + rt::Argument(ref arg) => { + // Fill in the format parameters into the formatter + self.fill = arg.format.fill; + self.align = arg.format.align; + self.flags = arg.format.flags; + self.width = self.getcount(&arg.format.width); + self.precision = self.getcount(&arg.format.precision); + + // Extract the correct argument + let value = match arg.position { + rt::ArgumentNext => { *self.curarg.next().unwrap() } + rt::ArgumentIs(i) => self.args[i], + }; + + // Then actually do some printing + match arg.method { + None => (value.formatter)(value.value, self), + Some(ref method) => self.execute(*method, value) + } + } + } + } + + fn getcount(&mut self, cnt: &rt::Count) -> Option { + match *cnt { + rt::CountIs(n) => { Some(n) } + rt::CountImplied => { None } + rt::CountIsParam(i) => { + let v = self.args[i].value; + unsafe { Some(*(v as *any::Void as *uint)) } + } + rt::CountIsNextParam => { + let v = self.curarg.next().unwrap().value; + unsafe { Some(*(v as *any::Void as *uint)) } + } + } + } + + fn execute(&mut self, method: &rt::Method, arg: Argument) -> Result { + match *method { + // Pluralization is selection upon a numeric value specified as the + // parameter. + rt::Plural(offset, ref selectors, ref default) => { + // This is validated at compile-time to be a pointer to a + // '&uint' value. + let value: &uint = unsafe { mem::transmute(arg.value) }; + let value = *value; + + // First, attempt to match against explicit values without the + // offsetted value + for s in selectors.iter() { + match s.selector { + rt::Literal(val) if value == val => { + return self.runplural(value, s.result); + } + _ => {} + } + } + + // Next, offset the value and attempt to match against the + // keyword selectors. + let value = value - match offset { Some(i) => i, None => 0 }; + for s in selectors.iter() { + let run = match s.selector { + rt::Keyword(rt::Zero) => value == 0, + rt::Keyword(rt::One) => value == 1, + rt::Keyword(rt::Two) => value == 2, + + // FIXME: Few/Many should have a user-specified boundary + // One possible option would be in the function + // pointer of the 'arg: Argument' struct. + rt::Keyword(rt::Few) => value < 8, + rt::Keyword(rt::Many) => value >= 8, + + rt::Literal(..) => false + }; + if run { + return self.runplural(value, s.result); + } + } + + self.runplural(value, *default) + } + + // Select is just a matching against the string specified. + rt::Select(ref selectors, ref default) => { + // This is validated at compile-time to be a pointer to a + // string slice, + let value: & &str = unsafe { mem::transmute(arg.value) }; + let value = *value; + + for s in selectors.iter() { + if s.selector == value { + for piece in s.result.iter() { + try!(self.run(piece, Some(value))); + } + return Ok(()); + } + } + for piece in default.iter() { + try!(self.run(piece, Some(value))); + } + Ok(()) + } + } + } + + fn runplural(&mut self, value: uint, pieces: &[rt::Piece]) -> Result { + ::uint::to_str_bytes(value, 10, |buf| { + let valuestr = str::from_utf8(buf).unwrap(); + for piece in pieces.iter() { + try!(self.run(piece, Some(valuestr))); + } + Ok(()) + }) + } + + // Helper methods used for padding and processing formatting arguments that + // all formatting traits can use. + + /// Performs the correct padding for an integer which has already been + /// emitted into a byte-array. The byte-array should *not* contain the sign + /// for the integer, that will be added by this method. + /// + /// # Arguments + /// + /// * is_positive - whether the original integer was positive or not. + /// * prefix - if the '#' character (FlagAlternate) is provided, this + /// is the prefix to put in front of the number. + /// * buf - the byte array that the number has been formatted into + /// + /// This function will correctly account for the flags provided as well as + /// the minimum width. It will not take precision into account. + pub fn pad_integral(&mut self, is_positive: bool, prefix: &str, buf: &[u8]) -> Result { + use fmt::rt::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad}; + + let mut width = buf.len(); + + let mut sign = None; + if !is_positive { + sign = Some('-'); width += 1; + } else if self.flags & (1 << (FlagSignPlus as uint)) != 0 { + sign = Some('+'); width += 1; + } + + let mut prefixed = false; + if self.flags & (1 << (FlagAlternate as uint)) != 0 { + prefixed = true; width += prefix.len(); + } + + // Writes the sign if it exists, and then the prefix if it was requested + let write_prefix = |f: &mut Formatter| { + for c in sign.move_iter() { try!(f.buf.write_char(c)); } + if prefixed { f.buf.write_str(prefix) } + else { Ok(()) } + }; + + // The `width` field is more of a `min-width` parameter at this point. + match self.width { + // If there's no minimum length requirements then we can just + // write the bytes. + None => { + try!(write_prefix(self)); self.buf.write(buf) + } + // Check if we're over the minimum width, if so then we can also + // just write the bytes. + Some(min) if width >= min => { + try!(write_prefix(self)); self.buf.write(buf) + } + // The sign and prefix goes before the padding if the fill character + // is zero + Some(min) if self.flags & (1 << (FlagSignAwareZeroPad as uint)) != 0 => { + self.fill = '0'; + try!(write_prefix(self)); + self.with_padding(min - width, rt::AlignRight, |f| f.buf.write(buf)) + } + // Otherwise, the sign and prefix goes after the padding + Some(min) => { + self.with_padding(min - width, rt::AlignRight, |f| { + try!(write_prefix(f)); f.buf.write(buf) + }) + } + } + } + + /// This function takes a string slice and emits it to the internal buffer + /// after applying the relevant formatting flags specified. The flags + /// recognized for generic strings are: + /// + /// * width - the minimum width of what to emit + /// * fill/align - what to emit and where to emit it if the string + /// provided needs to be padded + /// * precision - the maximum length to emit, the string is truncated if it + /// is longer than this length + /// + /// Notably this function ignored the `flag` parameters + pub fn pad(&mut self, s: &str) -> Result { + // Make sure there's a fast path up front + if self.width.is_none() && self.precision.is_none() { + return self.buf.write(s.as_bytes()); + } + // The `precision` field can be interpreted as a `max-width` for the + // string being formatted + match self.precision { + Some(max) => { + // If there's a maximum width and our string is longer than + // that, then we must always have truncation. This is the only + // case where the maximum length will matter. + let char_len = s.char_len(); + if char_len >= max { + let nchars = ::cmp::min(max, char_len); + return self.buf.write(s.slice_chars(0, nchars).as_bytes()); + } + } + None => {} + } + // The `width` field is more of a `min-width` parameter at this point. + match self.width { + // If we're under the maximum length, and there's no minimum length + // requirements, then we can just emit the string + None => self.buf.write(s.as_bytes()), + // If we're under the maximum width, check if we're over the minimum + // width, if so it's as easy as just emitting the string. + Some(width) if s.char_len() >= width => { + self.buf.write(s.as_bytes()) + } + // If we're under both the maximum and the minimum width, then fill + // up the minimum width with the specified string + some alignment. + Some(width) => { + self.with_padding(width - s.len(), rt::AlignLeft, |me| { + me.buf.write(s.as_bytes()) + }) + } + } + } + + /// Runs a callback, emitting the correct padding either before or + /// afterwards depending on whether right or left alingment is requested. + fn with_padding(&mut self, + padding: uint, + default: rt::Alignment, + f: |&mut Formatter| -> Result) -> Result { + let align = match self.align { + rt::AlignUnknown => default, + rt::AlignLeft | rt::AlignRight => self.align + }; + if align == rt::AlignLeft { + try!(f(self)); + } + let mut fill = [0u8, ..4]; + let len = self.fill.encode_utf8(fill); + for _ in range(0, padding) { + try!(self.buf.write(fill.slice_to(len))); + } + if align == rt::AlignRight { + try!(f(self)); + } + Ok(()) + } +} + +/// This is a function which calls are emitted to by the compiler itself to +/// create the Argument structures that are passed into the `format` function. +#[doc(hidden)] #[inline] +pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter) -> Result, + t: &'a T) -> Argument<'a> { + unsafe { + Argument { + formatter: mem::transmute(f), + value: mem::transmute(t) + } + } +} + +/// When the compiler determines that the type of an argument *must* be a string +/// (such as for select), then it invokes this method. +#[doc(hidden)] #[inline] +pub fn argumentstr<'a>(s: &'a &str) -> Argument<'a> { + argument(secret_string, s) +} + +/// When the compiler determines that the type of an argument *must* be a uint +/// (such as for plural), then it invokes this method. +#[doc(hidden)] #[inline] +pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { + argument(secret_unsigned, s) +} + +// Implementations of the core formatting traits + +impl Show for @T { + fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) } +} +impl Show for Box { + fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) } +} +impl<'a, T: Show> Show for &'a T { + fn fmt(&self, f: &mut Formatter) -> Result { secret_show(*self, f) } +} + +impl Bool for bool { + fn fmt(&self, f: &mut Formatter) -> Result { + secret_string(&(if *self {"true"} else {"false"}), f) + } +} + +impl<'a, T: str::Str> String for T { + fn fmt(&self, f: &mut Formatter) -> Result { + f.pad(self.as_slice()) + } +} + +impl Char for char { + fn fmt(&self, f: &mut Formatter) -> Result { + let mut utf8 = [0u8, ..4]; + let amt = self.encode_utf8(utf8); + let s: &str = unsafe { mem::transmute(utf8.slice_to(amt)) }; + secret_string(&s, f) + } +} + +macro_rules! floating(($ty:ident) => { + impl Float for $ty { + fn fmt(&self, fmt: &mut Formatter) -> Result { + // FIXME: this shouldn't perform an allocation + let s = match fmt.precision { + Some(i) => ::$ty::to_str_exact(self.abs(), i), + None => ::$ty::to_str_digits(self.abs(), 6) + }; + fmt.pad_integral(*self >= 0.0, "", s.as_bytes()) + } + } + + impl LowerExp for $ty { + fn fmt(&self, fmt: &mut Formatter) -> Result { + // FIXME: this shouldn't perform an allocation + let s = match fmt.precision { + Some(i) => ::$ty::to_str_exp_exact(self.abs(), i, false), + None => ::$ty::to_str_exp_digits(self.abs(), 6, false) + }; + fmt.pad_integral(*self >= 0.0, "", s.as_bytes()) + } + } + + impl UpperExp for $ty { + fn fmt(&self, fmt: &mut Formatter) -> Result { + // FIXME: this shouldn't perform an allocation + let s = match fmt.precision { + Some(i) => ::$ty::to_str_exp_exact(self.abs(), i, true), + None => ::$ty::to_str_exp_digits(self.abs(), 6, true) + }; + fmt.pad_integral(*self >= 0.0, "", s.as_bytes()) + } + } +}) +floating!(f32) +floating!(f64) + +impl Poly for T { + fn fmt(&self, f: &mut Formatter) -> Result { + match (f.width, f.precision) { + (None, None) => { + repr::write_repr(f.buf, self) + } + + // If we have a specified width for formatting, then we have to make + // this allocation of a new string + _ => { + let s = repr::repr_to_str(self); + f.pad(s) + } + } + } +} + +impl Pointer for *T { + fn fmt(&self, f: &mut Formatter) -> Result { + f.flags |= 1 << (rt::FlagAlternate as uint); + secret_lower_hex::(&(*self as uint), f) + } +} +impl Pointer for *mut T { + fn fmt(&self, f: &mut Formatter) -> Result { + secret_pointer::<*T>(&(*self as *T), f) + } +} +impl<'a, T> Pointer for &'a T { + fn fmt(&self, f: &mut Formatter) -> Result { + secret_pointer::<*T>(&(&**self as *T), f) + } +} +impl<'a, T> Pointer for &'a mut T { + fn fmt(&self, f: &mut Formatter) -> Result { + secret_pointer::<*T>(&(&**self as *T), f) + } +} + +// Implementation of Show for various core types + +macro_rules! delegate(($ty:ty to $other:ident) => { + impl<'a> Show for $ty { + fn fmt(&self, f: &mut Formatter) -> Result { + (concat_idents!(secret_, $other)(self, f)) + } + } +}) +delegate!(~str to string) +delegate!(&'a str to string) +delegate!(bool to bool) +delegate!(char to char) +delegate!(f32 to float) +delegate!(f64 to float) + +impl Show for *T { + fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer(self, f) } +} +impl Show for *mut T { + fn fmt(&self, f: &mut Formatter) -> Result { secret_pointer(self, f) } +} + +macro_rules! peel(($name:ident, $($other:ident,)*) => (tuple!($($other,)*))) + +macro_rules! tuple ( + () => (); + ( $($name:ident,)+ ) => ( + impl<$($name:Show),*> Show for ($($name,)*) { + #[allow(uppercase_variables, dead_assignment)] + fn fmt(&self, f: &mut Formatter) -> Result { + try!(write!(f.buf, "(")); + let ($(ref $name,)*) = *self; + let mut n = 0; + $( + if n > 0 { + try!(write!(f.buf, ", ")); + } + try!(write!(f.buf, "{}", *$name)); + n += 1; + )* + if n == 1 { + try!(write!(f.buf, ",")); + } + write!(f.buf, ")") + } + } + peel!($($name,)*) + ) +) + +tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } + +impl Show for Box { + fn fmt(&self, f: &mut Formatter) -> Result { f.pad("Box") } +} + +impl<'a> Show for &'a any::Any { + fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } +} + +impl Show for Option { + fn fmt(&self, f: &mut Formatter) -> Result { + match *self { + Some(ref t) => write!(f.buf, "Some({})", *t), + None => write!(f.buf, "None"), + } + } +} + +impl Show for ::result::Result { + fn fmt(&self, f: &mut Formatter) -> Result { + match *self { + Ok(ref t) => write!(f.buf, "Ok({})", *t), + Err(ref t) => write!(f.buf, "Err({})", *t), + } + } +} + +impl<'a, T: Show> Show for &'a [T] { + fn fmt(&self, f: &mut Formatter) -> Result { + if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 { + try!(write!(f.buf, "[")); + } + let mut is_first = true; + for x in self.iter() { + if is_first { + is_first = false; + } else { + try!(write!(f.buf, ", ")); + } + try!(write!(f.buf, "{}", *x)) + } + if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 { + try!(write!(f.buf, "]")); + } + Ok(()) + } +} + +impl<'a, T: Show> Show for &'a mut [T] { + fn fmt(&self, f: &mut Formatter) -> Result { + secret_show(&self.as_slice(), f) + } +} + +impl Show for ~[T] { + fn fmt(&self, f: &mut Formatter) -> Result { + secret_show(&self.as_slice(), f) + } +} + +impl Show for () { + fn fmt(&self, f: &mut Formatter) -> Result { + f.pad("()") + } +} + +impl Show for TypeId { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f.buf, "TypeId \\{ {} \\}", self.hash()) + } +} + +impl Show for iter::MinMaxResult { + fn fmt(&self, f: &mut Formatter) -> Result { + match *self { + iter::NoElements => + write!(f.buf, "NoElements"), + iter::OneElement(ref t) => + write!(f.buf, "OneElement({})", *t), + iter::MinMax(ref t1, ref t2) => + write!(f.buf, "MinMax({}, {})", *t1, *t2), + } + } +} + +impl Show for cmp::Ordering { + fn fmt(&self, f: &mut Formatter) -> Result { + match *self { + cmp::Less => write!(f.buf, "Less"), + cmp::Greater => write!(f.buf, "Greater"), + cmp::Equal => write!(f.buf, "Equal"), + } + } +} + +impl Show for Cell { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f.buf, r"Cell \{ value: {} \}", self.get()) + } +} + +impl Show for UTF16Item { + fn fmt(&self, f: &mut Formatter) -> Result { + match *self { + ScalarValue(c) => write!(f.buf, "ScalarValue({})", c), + LoneSurrogate(u) => write!(f.buf, "LoneSurrogate({})", u), + } + } +} + +// If you expected tests to be here, look instead at the run-pass/ifmt.rs test, +// it's a lot easier than creating all of the rt::Piece structures here. diff --git a/src/libstd/hash/mod.rs b/src/libstd/hash/mod.rs index a510aa90343e5..e6b7edb5a038e 100644 --- a/src/libstd/hash/mod.rs +++ b/src/libstd/hash/mod.rs @@ -63,7 +63,7 @@ #![allow(unused_must_use)] -use container::Container; +use collections::Collection; use intrinsics::TypeId; use io::Writer; use iter::Iterator; diff --git a/src/libstd/hash/sip.rs b/src/libstd/hash/sip.rs index 58e0f4c717ded..45db12050f4ab 100644 --- a/src/libstd/hash/sip.rs +++ b/src/libstd/hash/sip.rs @@ -25,7 +25,7 @@ */ use clone::Clone; -use container::Container; +use collections::Collection; use default::Default; use int; use io::{IoResult, Writer}; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 2880365cf348f..3154ddb8f02d1 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -11,7 +11,7 @@ //! Buffering wrappers for I/O traits use cmp; -use container::Container; +use collections::Collection; use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult}; use iter::ExactSize; use ops::Drop; diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 45f783698cd3b..a06d5aa88d66c 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -10,7 +10,7 @@ use clone::Clone; use cmp; -use container::Container; +use collections::Collection; use comm::{Sender, Receiver}; use io; use option::{None, Option, Some}; diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index 29afd2b1d9b2b..d61518d4ee76f 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -15,7 +15,7 @@ // FIXME: Not sure how this should be structured // FIXME: Iteration should probably be considered separately -use container::Container; +use collections::Collection; use iter::Iterator; use option::{Option, Some, None}; use result::{Ok, Err}; @@ -504,7 +504,7 @@ mod test { mod bench { extern crate test; - use container::Container; + use collections::Collection; use prelude::*; use self::test::Bencher; diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index a497ffd40a070..5e242cbaa1577 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -51,7 +51,7 @@ fs::unlink(&path); use c_str::ToCStr; use clone::Clone; -use container::Container; +use collections::Collection; use iter::Iterator; use kinds::Send; use super::{Reader, Writer, Seek}; diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index 92b546d5770e6..579509262ee5b 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -11,7 +11,7 @@ //! Readers and Writers for in-memory buffers use cmp::min; -use container::Container; +use collections::Collection; use option::None; use result::{Err, Ok}; use io; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index a043722581ba2..bc8f2ecf1adce 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -214,7 +214,7 @@ responding to errors that may occur while attempting to read the numbers. #![deny(unused_must_use)] use char::Char; -use container::Container; +use collections::Collection; use fmt; use int; use iter::Iterator; diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index f469c419e8ef7..9cf9d4d9e7756 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -15,7 +15,7 @@ #![allow(missing_doc)] -use container::Container; +use collections::Collection; use fmt; use from_str::FromStr; use iter::Iterator; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a9ec9c1ddc5ac..e8a7336a5873b 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -143,7 +143,7 @@ pub use core::cell; pub use core::char; pub use core::clone; #[cfg(not(test))] pub use core::cmp; -pub use core::container; +pub use core::collections; pub use core::default; pub use core::intrinsics; pub use core::iter; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index e58872b8395a6..23e82b3fcd6a8 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -12,7 +12,7 @@ use char; use clone::Clone; -use container::Container; +use collections::Collection; use iter::Iterator; use num::{NumCast, Zero, One, cast, Int}; use num::{Float, FPNaN, FPInfinite, ToPrimitive}; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index a4705b78caab7..b263a5547a0d5 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -29,7 +29,7 @@ #![allow(missing_doc)] use clone::Clone; -use container::Container; +use collections::Collection; use libc; use libc::{c_void, c_int}; use option::{Some, None, Option}; diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 2960d55f337c7..6073f0458b767 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -65,7 +65,7 @@ println!("path exists: {}", path.exists()); #![deny(deprecated_owned_vector)] -use container::Container; +use collections::Collection; use c_str::CString; use clone::Clone; use fmt; diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 4f7132dc6e442..f533b6d56f76b 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -10,7 +10,7 @@ //! POSIX file path handling -use container::Container; +use collections::Collection; use c_str::{CString, ToCStr}; use clone::Clone; use cmp::{Eq, TotalEq}; diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 176788edcc466..9cefcc49c2a8f 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -14,7 +14,7 @@ use ascii::AsciiCast; use c_str::{CString, ToCStr}; use clone::Clone; use cmp::{Eq, TotalEq}; -use container::Container; +use collections::Collection; use from_str::FromStr; use io::Writer; use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Rev, Iterator, Map}; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index e39d8d34447a4..a5488840e6bf7 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -58,7 +58,7 @@ pub use c_str::ToCStr; pub use char::Char; pub use clone::Clone; pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv}; -pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet}; +pub use collections::{Collection, Mutable, Map, MutableMap, Set, MutableSet}; pub use iter::{FromIterator, Extendable}; pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator}; pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize}; diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 35f32d0872802..25f085005452f 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -18,7 +18,7 @@ More runtime type reflection use mem::transmute; use char; -use container::Container; +use collections::Collection; use io; use iter::Iterator; use option::{Some, None, Option}; diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index f4cb770544c46..e1da07e72659a 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -13,7 +13,7 @@ #![allow(non_camel_case_types)] use char::Char; -use container::Container; +use collections::Collection; use from_str::from_str; use io::{IoResult, Writer}; use iter::Iterator; @@ -349,7 +349,7 @@ mod imp { #[cfg(not(target_os = "macos"))] fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> { - use container::Container; + use collections::Collection; use iter::Iterator; use os; use path::GenericPath; diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index c9e82bd16e541..e58d8ec86eab7 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use container::Container; +use collections::Collection; use fmt; use from_str::FromStr; use io::IoResult; diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index e78122f699d40..6e934b6ef2b73 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -101,7 +101,7 @@ use mem::transmute; use clone::Clone; use cmp::{TotalOrd, Ordering, Less, Greater}; use cmp; -use container::Container; +use collections::Collection; use iter::*; use mem::size_of; use mem; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 617887e8af3ea..fa5e118c0eb58 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -78,7 +78,7 @@ use char::Char; use char; use clone::Clone; use cmp::{Eq, TotalEq, Ord, TotalOrd, Equiv, Ordering}; -use container::Container; +use collections::Collection; use default::Default; use fmt; use from_str::FromStr; @@ -632,7 +632,7 @@ impl<'a> StrAllocating for MaybeOwned<'a> { } } -impl<'a> Container for MaybeOwned<'a> { +impl<'a> Collection for MaybeOwned<'a> { #[inline] fn len(&self) -> uint { self.as_slice().len() } } @@ -2098,7 +2098,7 @@ mod tests { #[test] fn test_str_container() { - fn sum_len(v: &[S]) -> uint { + fn sum_len(v: &[S]) -> uint { v.iter().map(|x| x.len()).sum() } diff --git a/src/libstd/strbuf.rs b/src/libstd/strbuf.rs index de480ef1b7fb7..b4dfc213ea66f 100644 --- a/src/libstd/strbuf.rs +++ b/src/libstd/strbuf.rs @@ -12,7 +12,7 @@ use c_vec::CVec; use char::Char; -use container::{Container, Mutable}; +use collections::{Collection, Mutable}; use fmt; use io::Writer; use iter::{Extendable, FromIterator, Iterator, range}; @@ -273,7 +273,7 @@ impl StrBuf { } } -impl Container for StrBuf { +impl Collection for StrBuf { #[inline] fn len(&self) -> uint { self.vec.len() @@ -340,7 +340,7 @@ impl ::hash::Hash for StrBuf { #[cfg(test)] mod tests { extern crate test; - use container::{Container, Mutable}; + use collections::{Collection, Mutable}; use self::test::Bencher; use str::{Str, StrSlice}; use super::StrBuf; diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 32883707615d5..ddc3c08b7434f 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -13,7 +13,7 @@ use RawVec = raw::Vec; use clone::Clone; use cmp::{Ord, Eq, Ordering, TotalEq, TotalOrd, max}; -use container::{Container, Mutable}; +use collections::{Collection, Mutable}; use default::Default; use fmt; use iter::{DoubleEndedIterator, FromIterator, Extendable, Iterator, range}; @@ -397,7 +397,7 @@ impl TotalOrd for Vec { } } -impl Container for Vec { +impl Collection for Vec { #[inline] fn len(&self) -> uint { self.len diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index f93c3576943ef..83a48131ebec8 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -121,7 +121,7 @@ impl Eq for OwnedSlice { impl TotalEq for OwnedSlice {} -impl Container for OwnedSlice { +impl Collection for OwnedSlice { fn len(&self) -> uint { self.len } } diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 693407b854fb9..a3b2c23dfdf2d 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -23,7 +23,7 @@ enum SmallVectorRepr { Many(Vec ), } -impl Container for SmallVector { +impl Collection for SmallVector { fn len(&self) -> uint { match self.repr { Zero => 0, diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index aa8cb84481f1e..2077911bf31e8 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -18,6 +18,6 @@ fn main() { let x: Box> = box HashMap::new(); let x: Box> = x; let y: Box> = box x; - //~^ ERROR failed to find an implementation of trait core::container::Map - // for ~core::container::Map:Send + //~^ ERROR failed to find an implementation of trait core::collections::Map + // for ~core::collections::Map:Send } diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index f02d41df21e4b..d6aa6b18c7dd2 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -48,7 +48,7 @@ impl cat { } } -impl Container for cat { +impl Collection for cat { fn len(&self) -> uint { self.meows as uint } fn is_empty(&self) -> bool { self.meows == 0 } } diff --git a/src/test/run-pass/send_str_hashmap.rs b/src/test/run-pass/send_str_hashmap.rs index 01ee61e1ed548..28db090b5afe3 100644 --- a/src/test/run-pass/send_str_hashmap.rs +++ b/src/test/run-pass/send_str_hashmap.rs @@ -10,7 +10,7 @@ extern crate collections; -use std::container::{Map, MutableMap}; +use std::collections::{Map, MutableMap}; use std::str::{SendStr, Owned, Slice}; use collections::HashMap; use std::option::Some; diff --git a/src/test/run-pass/send_str_treemap.rs b/src/test/run-pass/send_str_treemap.rs index b6dcf06cae04f..5687ce43d89c3 100644 --- a/src/test/run-pass/send_str_treemap.rs +++ b/src/test/run-pass/send_str_treemap.rs @@ -10,7 +10,7 @@ extern crate collections; -use std::container::{ Map, MutableMap}; +use std::collections::{ Map, MutableMap}; use std::str::{SendStr, Owned, Slice}; use std::to_str::ToStr; use self::collections::TreeMap;