#![allow(unused_variables)]
use any;
use cell::{Cell, RefCell, Ref, RefMut};
use char::CharExt;
use iter::{Iterator, IteratorExt, range};
use marker::{Copy, Sized};
use mem;
use option::Option;
use option::Option::{Some, None};
use result::Result::Ok;
use ops::{Deref, FnOnce, Index};
use result;
use slice::SliceExt;
use slice;
use str::{self, StrExt, Utf8Error};
pub use self::num::radix;
pub use self::num::Radix;
pub use self::num::RadixFmt;
mod num;
mod float;
pub mod rt;
#[experimental = "core and I/O reconciliation may alter this definition"]
pub type Result = result::Result<(), Error>;
#[experimental = "core and I/O reconciliation may alter this definition"]
#[derive(Copy)]
pub struct Error;
#[experimental = "waiting for core and I/O reconciliation"]
pub trait Writer {
fn write_str(&mut self, s: &str) -> Result;
fn write_fmt(&mut self, args: Arguments) -> Result {
struct Adapter<'a,T: ?Sized +'a>(&'a mut T);
impl<'a, T: ?Sized> Writer for Adapter<'a, T>
where T: Writer
{
fn write_str(&mut self, s: &str) -> Result {
self.0.write_str(s)
}
fn write_fmt(&mut self, args: Arguments) -> Result {
self.0.write_fmt(args)
}
}
write(&mut Adapter(self), args)
}
}
#[unstable = "name may change and implemented traits are also unstable"]
pub struct Formatter<'a> {
flags: uint,
fill: char,
align: rt::Alignment,
width: Option<uint>,
precision: Option<uint>,
buf: &'a mut (Writer+'a),
curarg: slice::Iter<'a, Argument<'a>>,
args: &'a [Argument<'a>],
}
enum Void {}
#[experimental = "implementation detail of the `format_args!` macro"]
#[derive(Copy)]
pub struct Argument<'a> {
value: &'a Void,
formatter: fn(&Void, &mut Formatter) -> Result,
}
impl<'a> Argument<'a> {
#[inline(never)]
fn show_uint(x: &uint, f: &mut Formatter) -> Result {
Show::fmt(x, f)
}
fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter) -> Result) -> Argument<'b> {
unsafe {
Argument {
formatter: mem::transmute(f),
value: mem::transmute(x)
}
}
}
fn from_uint(x: &uint) -> Argument {
Argument::new(x, Argument::show_uint)
}
fn as_uint(&self) -> Option<uint> {
if self.formatter as uint == Argument::show_uint as uint {
Some(unsafe { *(self.value as *const _ as *const uint) })
} else {
None
}
}
}
impl<'a> Arguments<'a> {
#[doc(hidden)] #[inline]
#[experimental = "implementation detail of the `format_args!` macro"]
pub fn new(pieces: &'a [&'a str],
args: &'a [Argument<'a>]) -> Arguments<'a> {
Arguments {
pieces: pieces,
fmt: None,
args: args
}
}
#[doc(hidden)] #[inline]
#[experimental = "implementation detail of the `format_args!` macro"]
pub fn with_placeholders(pieces: &'a [&'a str],
fmt: &'a [rt::Argument<'a>],
args: &'a [Argument<'a>]) -> Arguments<'a> {
Arguments {
pieces: pieces,
fmt: Some(fmt),
args: args
}
}
}
#[stable]
#[derive(Copy)]
pub struct Arguments<'a> {
pieces: &'a [&'a str],
fmt: Option<&'a [rt::Argument<'a>]>,
args: &'a [Argument<'a>],
}
impl<'a> Show for Arguments<'a> {
fn fmt(&self, fmt: &mut Formatter) -> Result {
String::fmt(self, fmt)
}
}
impl<'a> String for Arguments<'a> {
fn fmt(&self, fmt: &mut Formatter) -> Result {
write(fmt.buf, *self)
}
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait Show {
fn fmt(&self, &mut Formatter) -> Result;
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait String {
fn fmt(&self, &mut Formatter) -> Result;
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait Octal {
fn fmt(&self, &mut Formatter) -> Result;
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait Binary {
fn fmt(&self, &mut Formatter) -> Result;
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait LowerHex {
fn fmt(&self, &mut Formatter) -> Result;
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait UpperHex {
fn fmt(&self, &mut Formatter) -> Result;
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait Pointer {
fn fmt(&self, &mut Formatter) -> Result;
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait LowerExp {
fn fmt(&self, &mut Formatter) -> Result;
}
#[unstable = "I/O and core have yet to be reconciled"]
pub trait UpperExp {
fn fmt(&self, &mut Formatter) -> Result;
}
#[experimental = "libcore and I/O have yet to be reconciled, and this is an \
implementation detail which should not otherwise be exported"]
pub fn write(output: &mut Writer, args: Arguments) -> Result {
let mut formatter = Formatter {
flags: 0,
width: None,
precision: None,
buf: output,
align: rt::AlignUnknown,
fill: ' ',
args: args.args,
curarg: args.args.iter(),
};
let mut pieces = args.pieces.iter();
match args.fmt {
None => {
for (arg, piece) in args.args.iter().zip(pieces.by_ref()) {
try!(formatter.buf.write_str(*piece));
try!((arg.formatter)(arg.value, &mut formatter));
}
}
Some(fmt) => {
for (arg, piece) in fmt.iter().zip(pieces.by_ref()) {
try!(formatter.buf.write_str(*piece));
try!(formatter.run(arg));
}
}
}
match pieces.next() {
Some(piece) => {
try!(formatter.buf.write_str(*piece));
}
None => {}
}
Ok(())
}
impl<'a> Formatter<'a> {
fn run(&mut self, arg: &rt::Argument) -> Result {
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);
let value = match arg.position {
rt::ArgumentNext => { *self.curarg.next().unwrap() }
rt::ArgumentIs(i) => self.args[i],
};
(value.formatter)(value.value, self)
}
fn getcount(&mut self, cnt: &rt::Count) -> Option<uint> {
match *cnt {
rt::CountIs(n) => Some(n),
rt::CountImplied => None,
rt::CountIsParam(i) => {
self.args[i].as_uint()
}
rt::CountIsNextParam => {
self.curarg.next().and_then(|arg| arg.as_uint())
}
}
}
#[unstable = "definition may change slightly over time"]
pub fn pad_integral(&mut self,
is_positive: bool,
prefix: &str,
buf: &str)
-> Result {
use char::CharExt;
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.char_len();
}
let write_prefix = |&: f: &mut Formatter| {
for c in sign.into_iter() {
let mut b = [0; 4];
let n = c.encode_utf8(&mut b).unwrap_or(0);
let b = unsafe { str::from_utf8_unchecked(b.index(&(0..n))) };
try!(f.buf.write_str(b));
}
if prefixed { f.buf.write_str(prefix) }
else { Ok(()) }
};
match self.width {
None => {
try!(write_prefix(self)); self.buf.write_str(buf)
}
Some(min) if width >= min => {
try!(write_prefix(self)); self.buf.write_str(buf)
}
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_str(buf)
})
}
Some(min) => {
self.with_padding(min - width, rt::AlignRight, |f| {
try!(write_prefix(f)); f.buf.write_str(buf)
})
}
}
}
#[unstable = "definition may change slightly over time"]
pub fn pad(&mut self, s: &str) -> Result {
if self.width.is_none() && self.precision.is_none() {
return self.buf.write_str(s);
}
match self.precision {
Some(max) => {
let char_len = s.char_len();
if char_len >= max {
let nchars = ::cmp::min(max, char_len);
return self.buf.write_str(s.slice_chars(0, nchars));
}
}
None => {}
}
match self.width {
None => self.buf.write_str(s),
Some(width) if s.char_len() >= width => {
self.buf.write_str(s)
}
Some(width) => {
self.with_padding(width - s.char_len(), rt::AlignLeft, |me| {
me.buf.write_str(s)
})
}
}
}
fn with_padding<F>(&mut self, padding: uint, default: rt::Alignment, f: F) -> Result where
F: FnOnce(&mut Formatter) -> Result,
{
use char::CharExt;
let align = match self.align {
rt::AlignUnknown => default,
_ => self.align
};
let (pre_pad, post_pad) = match align {
rt::AlignLeft => (0u, padding),
rt::AlignRight | rt::AlignUnknown => (padding, 0u),
rt::AlignCenter => (padding / 2, (padding + 1) / 2),
};
let mut fill = [0u8; 4];
let len = self.fill.encode_utf8(&mut fill).unwrap_or(0);
let fill = unsafe { str::from_utf8_unchecked(fill.index(&(..len))) };
for _ in range(0, pre_pad) {
try!(self.buf.write_str(fill));
}
try!(f(self));
for _ in range(0, post_pad) {
try!(self.buf.write_str(fill));
}
Ok(())
}
#[unstable = "reconciling core and I/O may alter this definition"]
pub fn write_str(&mut self, data: &str) -> Result {
self.buf.write_str(data)
}
#[unstable = "reconciling core and I/O may alter this definition"]
pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
write(self.buf, fmt)
}
#[experimental = "return type may change and method was just created"]
pub fn flags(&self) -> uint { self.flags }
#[unstable = "method was just created"]
pub fn fill(&self) -> char { self.fill }
#[unstable = "method was just created"]
pub fn align(&self) -> rt::Alignment { self.align }
#[unstable = "method was just created"]
pub fn width(&self) -> Option<uint> { self.width }
#[unstable = "method was just created"]
pub fn precision(&self) -> Option<uint> { self.precision }
}
impl Show for Error {
fn fmt(&self, f: &mut Formatter) -> Result {
String::fmt("an error occurred when formatting an argument", f)
}
}
#[doc(hidden)] #[inline]
#[experimental = "implementation detail of the `format_args!` macro"]
pub fn argument<'a, T>(f: fn(&T, &mut Formatter) -> Result,
t: &'a T) -> Argument<'a> {
Argument::new(t, f)
}
#[doc(hidden)] #[inline]
#[experimental = "implementation detail of the `format_args!` macro"]
pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
Argument::from_uint(s)
}
macro_rules! fmt_refs {
($($tr:ident),*) => {
$(
impl<'a, T: ?Sized + $tr> $tr for &'a T {
fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) }
}
impl<'a, T: ?Sized + $tr> $tr for &'a mut T {
fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) }
}
)*
}
}
fmt_refs! { Show, String, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }
impl Show for bool {
fn fmt(&self, f: &mut Formatter) -> Result {
String::fmt(self, f)
}
}
impl String for bool {
fn fmt(&self, f: &mut Formatter) -> Result {
String::fmt(if *self { "true" } else { "false" }, f)
}
}
#[cfg(stage0)]
impl Show for str {
fn fmt(&self, f: &mut Formatter) -> Result {
String::fmt(self, f)
}
}
#[cfg(not(stage0))]
impl Show for str {
fn fmt(&self, f: &mut Formatter) -> Result {
try!(write!(f, "\""));
for c in self.chars().flat_map(|c| c.escape_default()) {
try!(write!(f, "{}", c));
}
write!(f, "\"")
}
}
impl String for str {
fn fmt(&self, f: &mut Formatter) -> Result {
f.pad(self)
}
}
#[cfg(stage0)]
impl Show for char {
fn fmt(&self, f: &mut Formatter) -> Result {
String::fmt(self, f)
}
}
#[cfg(not(stage0))]
impl Show for char {
fn fmt(&self, f: &mut Formatter) -> Result {
use char::CharExt;
try!(write!(f, "'"));
for c in self.escape_default() {
try!(write!(f, "{}", c));
}
write!(f, "'")
}
}
impl String for char {
fn fmt(&self, f: &mut Formatter) -> Result {
let mut utf8 = [0u8; 4];
let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
let s: &str = unsafe { mem::transmute(utf8.index(&(0..amt))) };
String::fmt(s, f)
}
}
impl<T> Pointer for *const T {
fn fmt(&self, f: &mut Formatter) -> Result {
f.flags |= 1 << (rt::FlagAlternate as uint);
let ret = LowerHex::fmt(&(*self as uint), f);
f.flags &= !(1 << (rt::FlagAlternate as uint));
ret
}
}
impl<T> Pointer for *mut T {
fn fmt(&self, f: &mut Formatter) -> Result {
Pointer::fmt(&(*self as *const T), f)
}
}
impl<'a, T> Pointer for &'a T {
fn fmt(&self, f: &mut Formatter) -> Result {
Pointer::fmt(&(*self as *const T), f)
}
}
impl<'a, T> Pointer for &'a mut T {
fn fmt(&self, f: &mut Formatter) -> Result {
Pointer::fmt(&(&**self as *const T), f)
}
}
macro_rules! floating { ($ty:ident) => {
impl Show for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
try!(String::fmt(self, fmt));
fmt.write_str(stringify!($ty))
}
}
impl String for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision {
Some(i) => float::DigExact(i),
None => float::DigMax(6),
};
float::float_to_str_bytes_common(self.abs(),
10,
true,
float::SignNeg,
digits,
float::ExpNone,
false,
|bytes| {
fmt.pad_integral(self.is_nan() || *self >= 0.0, "", bytes)
})
}
}
impl LowerExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision {
Some(i) => float::DigExact(i),
None => float::DigMax(6),
};
float::float_to_str_bytes_common(self.abs(),
10,
true,
float::SignNeg,
digits,
float::ExpDec,
false,
|bytes| {
fmt.pad_integral(self.is_nan() || *self >= 0.0, "", bytes)
})
}
}
impl UpperExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision {
Some(i) => float::DigExact(i),
None => float::DigMax(6),
};
float::float_to_str_bytes_common(self.abs(),
10,
true,
float::SignNeg,
digits,
float::ExpDec,
true,
|bytes| {
fmt.pad_integral(self.is_nan() || *self >= 0.0, "", bytes)
})
}
}
} }
floating! { f32 }
floating! { f64 }
impl<T> Show for *const T {
fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
}
impl<T> String for *const T {
fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
}
impl<T> Show for *mut T {
fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
}
impl<T> String for *mut T {
fn fmt(&self, f: &mut Formatter) -> Result { Pointer::fmt(self, f) }
}
macro_rules! peel {
($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })
}
macro_rules! tuple {
() => ();
( $($name:ident,)+ ) => (
impl<$($name:Show),*> Show for ($($name,)*) {
#[allow(non_snake_case, unused_assignments)]
fn fmt(&self, f: &mut Formatter) -> Result {
try!(write!(f, "("));
let ($(ref $name,)*) = *self;
let mut n = 0i;
$(
if n > 0 {
try!(write!(f, ", "));
}
try!(write!(f, "{:?}", *$name));
n += 1;
)*
if n == 1 {
try!(write!(f, ","));
}
write!(f, ")")
}
}
peel! { $($name,)* }
)
}
tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
impl<'a> Show for &'a (any::Any+'a) {
fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") }
}
impl<T: Show> Show for [T] {
fn fmt(&self, f: &mut Formatter) -> Result {
if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
try!(write!(f, "["));
}
let mut is_first = true;
for x in self.iter() {
if is_first {
is_first = false;
} else {
try!(write!(f, ", "));
}
try!(write!(f, "{:?}", *x))
}
if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
try!(write!(f, "]"));
}
Ok(())
}
}
#[cfg(stage0)]
impl<T: Show> String for [T] {
fn fmt(&self, f: &mut Formatter) -> Result {
if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
try!(write!(f, "["));
}
let mut is_first = true;
for x in self.iter() {
if is_first {
is_first = false;
} else {
try!(write!(f, ", "));
}
try!(write!(f, "{}", *x))
}
if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
try!(write!(f, "]"));
}
Ok(())
}
}
#[cfg(not(stage0))]
impl<T: String> String for [T] {
fn fmt(&self, f: &mut Formatter) -> Result {
if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
try!(write!(f, "["));
}
let mut is_first = true;
for x in self.iter() {
if is_first {
is_first = false;
} else {
try!(write!(f, ", "));
}
try!(write!(f, "{}", *x))
}
if f.flags & (1 << (rt::FlagAlternate as uint)) == 0 {
try!(write!(f, "]"));
}
Ok(())
}
}
impl Show for () {
fn fmt(&self, f: &mut Formatter) -> Result {
f.pad("()")
}
}
impl String for () {
fn fmt(&self, f: &mut Formatter) -> Result {
f.pad("()")
}
}
impl<T: Copy + Show> Show for Cell<T> {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "Cell {{ value: {:?} }}", self.get())
}
}
#[unstable]
impl<T: Show> Show for RefCell<T> {
fn fmt(&self, f: &mut Formatter) -> Result {
match self.try_borrow() {
Some(val) => write!(f, "RefCell {{ value: {:?} }}", val),
None => write!(f, "RefCell {{ <borrowed> }}")
}
}
}
impl<'b, T: Show> Show for Ref<'b, T> {
fn fmt(&self, f: &mut Formatter) -> Result {
Show::fmt(&**self, f)
}
}
impl<'b, T: Show> Show for RefMut<'b, T> {
fn fmt(&self, f: &mut Formatter) -> Result {
Show::fmt(&*(self.deref()), f)
}
}
impl String for Utf8Error {
fn fmt(&self, f: &mut Formatter) -> Result {
match *self {
Utf8Error::InvalidByte(n) => {
write!(f, "invalid utf-8: invalid byte at index {}", n)
}
Utf8Error::TooShort => {
write!(f, "invalid utf-8: byte slice too short")
}
}
}
}