diff options
Diffstat (limited to 'src/libstd/repr.rs')
| -rw-r--r-- | src/libstd/repr.rs | 206 |
1 files changed, 118 insertions, 88 deletions
diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 41ddf027787..f71649602b2 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -21,48 +21,57 @@ use char; use container::Container; use io; use iter::Iterator; -use option::{Some, None}; +use option::{Some, None, Option}; use ptr; use reflect; use reflect::{MovePtr, align}; +use result::{Ok, Err}; use str::StrSlice; use to_str::ToStr; use vec::OwnedVector; use unstable::intrinsics::{Disr, Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc}; use unstable::raw; +macro_rules! if_ok( ($me:expr, $e:expr) => ( + match $e { + Ok(()) => {}, + Err(e) => { $me.last_err = Some(e); return false; } + } +) ) + /// Representations trait Repr { - fn write_repr(&self, writer: &mut io::Writer); + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()>; } impl Repr for () { - fn write_repr(&self, writer: &mut io::Writer) { - writer.write("()".as_bytes()); + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { + writer.write("()".as_bytes()) } } impl Repr for bool { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { let s = if *self { "true" } else { "false" }; writer.write(s.as_bytes()) } } impl Repr for int { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { ::int::to_str_bytes(*self, 10u, |bits| { - writer.write(bits); + writer.write(bits) }) } } macro_rules! int_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { ::$ty::to_str_bytes(*self, 10u, |bits| { - writer.write(bits); - writer.write(bytes!($suffix)); + writer.write(bits).and_then(|()| { + writer.write(bytes!($suffix)) + }) }) } })) @@ -78,10 +87,11 @@ int_repr!(u32, "u32") int_repr!(u64, "u64") macro_rules! num_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { let s = self.to_str(); - writer.write(s.as_bytes()); - writer.write(bytes!($suffix)); + writer.write(s.as_bytes()).and_then(|()| { + writer.write(bytes!($suffix)) + }) } })) @@ -100,7 +110,8 @@ pub struct ReprVisitor<'a> { priv ptr: *u8, priv ptr_stk: ~[*u8], priv var_stk: ~[VariantState], - priv writer: &'a mut io::Writer + priv writer: &'a mut io::Writer, + priv last_err: Option<io::IoError>, } pub fn ReprVisitor<'a>(ptr: *u8, @@ -110,6 +121,7 @@ pub fn ReprVisitor<'a>(ptr: *u8, ptr_stk: ~[], var_stk: ~[], writer: writer, + last_err: None, } } @@ -130,11 +142,10 @@ impl<'a> ReprVisitor<'a> { // Various helpers for the TyVisitor impl #[inline] - pub fn get<T>(&mut self, f: |&mut ReprVisitor, &T|) -> bool { + pub fn get<T>(&mut self, f: |&mut ReprVisitor, &T| -> bool) -> bool { unsafe { - f(self, transmute::<*u8,&T>(self.ptr)); + f(self, transmute::<*u8,&T>(self.ptr)) } - true } #[inline] @@ -152,43 +163,53 @@ impl<'a> ReprVisitor<'a> { ptr_stk: ~[], var_stk: ~[], writer: ::cast::transmute_copy(&self.writer), + last_err: None, }; let mut v = reflect::MovePtrAdaptor(u); // Obviously this should not be a thing, but blame #8401 for now visit_tydesc(inner, &mut v as &mut TyVisitor); - true + match v.unwrap().last_err { + Some(e) => { + self.last_err = Some(e); + false + } + None => true, + } } } #[inline] pub fn write<T:Repr>(&mut self) -> bool { self.get(|this, v:&T| { - v.write_repr(unsafe { ::cast::transmute_copy(&this.writer) }); + if_ok!(this, v.write_repr(this.writer)); + true }) } - pub fn write_escaped_slice(&mut self, slice: &str) { - self.writer.write(['"' as u8]); + pub fn write_escaped_slice(&mut self, slice: &str) -> bool { + if_ok!(self, self.writer.write(['"' as u8])); for ch in slice.chars() { - self.write_escaped_char(ch, true); + if !self.write_escaped_char(ch, true) { return false } } - self.writer.write(['"' as u8]); + if_ok!(self, self.writer.write(['"' as u8])); + true } - pub fn write_mut_qualifier(&mut self, mtbl: uint) { + pub fn write_mut_qualifier(&mut self, mtbl: uint) -> bool { if mtbl == 0 { - self.writer.write("mut ".as_bytes()); + if_ok!(self, self.writer.write("mut ".as_bytes())); } else if mtbl == 1 { // skip, this is ast::m_imm } else { fail!("invalid mutability value"); } + true } pub fn write_vec_range(&mut self, ptr: *(), len: uint, inner: *TyDesc) -> bool { let mut p = ptr as *u8; let (sz, al) = unsafe { ((*inner).size, (*inner).align) }; - self.writer.write(['[' as u8]); + if_ok!(self, self.writer.write(['[' as u8])); let mut first = true; let mut left = len; // unit structs have 0 size, and don't loop forever. @@ -197,13 +218,13 @@ impl<'a> ReprVisitor<'a> { if first { first = false; } else { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.visit_ptr_inner(p as *u8, inner); p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8; left -= dec; } - self.writer.write([']' as u8]); + if_ok!(self, self.writer.write([']' as u8])); true } @@ -211,8 +232,8 @@ impl<'a> ReprVisitor<'a> { self.write_vec_range(ptr::to_unsafe_ptr(&v.data), v.fill, inner) } - fn write_escaped_char(&mut self, ch: char, is_str: bool) { - match ch { + fn write_escaped_char(&mut self, ch: char, is_str: bool) -> bool { + if_ok!(self, match ch { '\t' => self.writer.write("\\t".as_bytes()), '\r' => self.writer.write("\\r".as_bytes()), '\n' => self.writer.write("\\n".as_bytes()), @@ -234,16 +255,18 @@ impl<'a> ReprVisitor<'a> { '\x20'..'\x7e' => self.writer.write([ch as u8]), _ => { char::escape_unicode(ch, |c| { - self.writer.write([c as u8]); - }) + let _ = self.writer.write([c as u8]); + }); + Ok(()) } - } + }); + return true; } } impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_bot(&mut self) -> bool { - self.writer.write("!".as_bytes()); + if_ok!(self, self.writer.write("!".as_bytes())); true } fn visit_nil(&mut self) -> bool { self.write::<()>() } @@ -265,9 +288,10 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_char(&mut self) -> bool { self.get::<char>(|this, &ch| { - this.writer.write(['\'' as u8]); - this.write_escaped_char(ch, false); - this.writer.write(['\'' as u8]); + if_ok!(this, this.writer.write(['\'' as u8])); + if !this.write_escaped_char(ch, false) { return false } + if_ok!(this, this.writer.write(['\'' as u8])); + true }) } @@ -277,8 +301,8 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_estr_uniq(&mut self) -> bool { self.get::<~str>(|this, s| { - this.writer.write(['~' as u8]); - this.write_escaped_slice(*s); + if_ok!(this, this.writer.write(['~' as u8])); + this.write_escaped_slice(*s) }) } @@ -291,34 +315,35 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _align: uint) -> bool { fail!(); } fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['@' as u8]); + if_ok!(self, self.writer.write(['@' as u8])); self.write_mut_qualifier(mtbl); self.get::<&raw::Box<()>>(|this, b| { let p = ptr::to_unsafe_ptr(&b.data) as *u8; - this.visit_ptr_inner(p, inner); + this.visit_ptr_inner(p, inner) }) } fn visit_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['~' as u8]); + if_ok!(self, self.writer.write(['~' as u8])); self.get::<*u8>(|this, b| { - this.visit_ptr_inner(*b, inner); + this.visit_ptr_inner(*b, inner) }) } fn visit_ptr(&mut self, mtbl: uint, _inner: *TyDesc) -> bool { self.get::<*u8>(|this, p| { - write!(this.writer, "({} as *", *p); + if_ok!(this, write!(this.writer, "({} as *", *p)); this.write_mut_qualifier(mtbl); - this.writer.write("())".as_bytes()); + if_ok!(this, this.writer.write("())".as_bytes())); + true }) } fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['&' as u8]); + if_ok!(self, self.writer.write(['&' as u8])); self.write_mut_qualifier(mtbl); self.get::<*u8>(|this, p| { - this.visit_ptr_inner(*p, inner); + this.visit_ptr_inner(*p, inner) }) } @@ -327,33 +352,33 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<raw::Vec<()>>(|this, b| { - this.write_unboxed_vec_repr(mtbl, b, inner); + this.write_unboxed_vec_repr(mtbl, b, inner) }) } fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<&raw::Box<raw::Vec<()>>>(|this, b| { - this.writer.write(['@' as u8]); + if_ok!(this, this.writer.write(['@' as u8])); this.write_mut_qualifier(mtbl); - this.write_unboxed_vec_repr(mtbl, &b.data, inner); + this.write_unboxed_vec_repr(mtbl, &b.data, inner) }) } fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<&raw::Vec<()>>(|this, b| { - this.writer.write(['~' as u8]); - this.write_unboxed_vec_repr(mtbl, *b, inner); + if_ok!(this, this.writer.write(['~' as u8])); + this.write_unboxed_vec_repr(mtbl, *b, inner) }) } fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<raw::Slice<()>>(|this, s| { - this.writer.write(['&' as u8]); + if_ok!(this, this.writer.write(['&' as u8])); this.write_mut_qualifier(mtbl); let size = unsafe { if (*inner).size == 0 { 1 } else { (*inner).size } }; - this.write_vec_range(s.data, s.len * size, inner); + this.write_vec_range(s.data, s.len * size, inner) }) } @@ -361,42 +386,42 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _: uint, inner: *TyDesc) -> bool { let assumed_size = if sz == 0 { n } else { sz }; self.get::<()>(|this, b| { - this.write_vec_range(ptr::to_unsafe_ptr(b), assumed_size, inner); + this.write_vec_range(ptr::to_unsafe_ptr(b), assumed_size, inner) }) } fn visit_enter_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['{' as u8]); + if_ok!(self, self.writer.write(['{' as u8])); true } fn visit_rec_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.write_mut_qualifier(mtbl); - self.writer.write(name.as_bytes()); - self.writer.write(": ".as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); + if_ok!(self, self.writer.write(": ".as_bytes())); self.visit_inner(inner); true } fn visit_leave_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['}' as u8]); + if_ok!(self, self.writer.write(['}' as u8])); true } fn visit_enter_class(&mut self, name: &str, named_fields: bool, n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); if n_fields != 0 { if named_fields { - self.writer.write(['{' as u8]); + if_ok!(self, self.writer.write(['{' as u8])); } else { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); } } true @@ -405,11 +430,11 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_class_field(&mut self, i: uint, name: &str, named: bool, _mtbl: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } if named { - self.writer.write(name.as_bytes()); - self.writer.write(": ".as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); + if_ok!(self, self.writer.write(": ".as_bytes())); } self.visit_inner(inner); true @@ -419,9 +444,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _sz: uint, _align: uint) -> bool { if n_fields != 0 { if named_fields { - self.writer.write(['}' as u8]); + if_ok!(self, self.writer.write(['}' as u8])); } else { - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); } } true @@ -429,13 +454,13 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_enter_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); true } fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.visit_inner(inner); true @@ -444,9 +469,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_leave_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { if _n_fields == 1 { - self.writer.write([',' as u8]); + if_ok!(self, self.writer.write([',' as u8])); } - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); true } @@ -482,9 +507,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { } if write { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); if n_fields > 0 { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); } } true @@ -498,7 +523,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { match self.var_stk[self.var_stk.len() - 1] { Matched => { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } if ! self.visit_inner(inner) { return false; @@ -516,7 +541,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { match self.var_stk[self.var_stk.len() - 1] { Matched => { if n_fields > 0 { - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); } } _ => () @@ -538,28 +563,29 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_enter_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { - self.writer.write("fn(".as_bytes()); + if_ok!(self, self.writer.write("fn(".as_bytes())); true } fn visit_fn_input(&mut self, i: uint, _mode: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } let name = unsafe { (*inner).name }; - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); true } - fn visit_fn_output(&mut self, _retstyle: uint, variadic: bool, inner: *TyDesc) -> bool { + fn visit_fn_output(&mut self, _retstyle: uint, variadic: bool, + inner: *TyDesc) -> bool { if variadic { - self.writer.write(", ...".as_bytes()); + if_ok!(self, self.writer.write(", ...".as_bytes())); } - self.writer.write(")".as_bytes()); + if_ok!(self, self.writer.write(")".as_bytes())); let name = unsafe { (*inner).name }; if name != "()" { - self.writer.write(" -> ".as_bytes()); - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(" -> ".as_bytes())); + if_ok!(self, self.writer.write(name.as_bytes())); } true } @@ -569,7 +595,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_trait(&mut self, name: &str) -> bool { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); true } @@ -582,13 +608,17 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } } -pub fn write_repr<T>(writer: &mut io::Writer, object: &T) { +pub fn write_repr<T>(writer: &mut io::Writer, object: &T) -> io::IoResult<()> { unsafe { let ptr = ptr::to_unsafe_ptr(object) as *u8; let tydesc = get_tydesc::<T>(); let u = ReprVisitor(ptr, writer); let mut v = reflect::MovePtrAdaptor(u); visit_tydesc(tydesc, &mut v as &mut TyVisitor); + match v.unwrap().last_err { + Some(e) => Err(e), + None => Ok(()), + } } } @@ -597,7 +627,7 @@ pub fn repr_to_str<T>(t: &T) -> ~str { use io; let mut result = io::MemWriter::new(); - write_repr(&mut result as &mut io::Writer, t); + write_repr(&mut result as &mut io::Writer, t).unwrap(); str::from_utf8_owned(result.unwrap()).unwrap() } @@ -615,7 +645,7 @@ fn test_repr() { fn exact_test<T>(t: &T, e:&str) { let mut m = io::MemWriter::new(); - write_repr(&mut m as &mut io::Writer, t); + write_repr(&mut m as &mut io::Writer, t).unwrap(); let s = str::from_utf8_owned(m.unwrap()).unwrap(); assert_eq!(s.as_slice(), e); } |
