use std::cell::*;
use std::hash::Hash;
use std::ops::Deref;
use std::collections::{HashSet, HashMap};
pub trait Show {
fn show(&self) -> String;
}
macro_rules! simple_show_impls {
($($tr:ty),*) => {
$(
impl Show for $tr {
fn show(&self) -> String { self.to_string() }
}
)*
}
}
simple_show_impls!(i8,
i16,
i32,
i64,
u8,
u16,
u32,
u64,
isize,
usize,
f32,
f64,
bool);
impl Show for &'static str {
fn show(&self) -> String {
(*self).show()
}
}
impl Show for str {
fn show(&self) -> String {
format!("\"{}\"", self)
}
}
impl Show for char {
fn show(&self) -> String {
format!("'{}'", self)
}
}
impl<T: Show> Show for [T] {
fn show(&self) -> String {
let shown = self.iter()
.map(|i| i.show())
.collect::<Vec<String>>();
format!("[{}]", shown.join(", "))
}
}
impl Show for () {
fn show(&self) -> String {
String::from("()")
}
}
impl<T: Show + Copy> Show for Cell<T> {
fn show(&self) -> String {
self.get().show()
}
}
impl<'b, T: Show> Show for Ref<'b, T> {
fn show(&self) -> String {
self.deref().show()
}
}
impl<'b, T: Show> Show for RefMut<'b, T> {
fn show(&self) -> String {
self.deref().show()
}
}
impl<T: Show> Show for RefCell<T> {
fn show(&self) -> String {
format!("RefCell(value={})", self.borrow().show())
}
}
impl<T: Show> Show for Option<T> {
fn show(&self) -> String {
match *self {
Some(ref v) => format!("Some({})", v.show()),
Option::None => String::from("None"),
}
}
}
impl<T> Show for HashSet<T>
where T: Show + Eq + Hash
{
fn show(&self) -> String {
let shown = self.into_iter()
.map(|i| i.show())
.collect::<Vec<String>>();
format!("HashSet({})", shown.join(", "))
}
}
impl<K, V> Show for HashMap<K, V>
where K: Show + Eq + Hash,
V: Show
{
fn show(&self) -> String {
let shown = self.into_iter()
.map(|(k, v)| format!("{} -> {}", k.show(), v.show()))
.collect::<Vec<String>>();
format!("HashMap({})", shown.join(", "))
}
}
impl<T: Show> Show for Box<T> {
fn show(&self) -> String {
format!("Box({})", self.deref().show())
}
}
macro_rules! tuple_impls {
() => {};
(($idx:tt => $typ:ident), $( ($nidx:tt => $ntyp:ident), )*) => {
tuple_impls!([($idx, $typ);] $( ($nidx => $ntyp), )*);
tuple_impls!($( ($nidx => $ntyp), )*); };
([$(($accIdx: tt, $accTyp: ident);)+] ($idx:tt => $typ:ident), $( ($nidx:tt => $ntyp:ident), )*) => {
tuple_impls!([($idx, $typ); $(($accIdx, $accTyp); )*] $( ($nidx => $ntyp), ) *);
};
([($idx:tt, $typ:ident); $( ($nidx:tt, $ntyp:ident); )*]) => {
impl<$typ: Show, $( $ntyp: Show),*> Show for ($typ, $( $ntyp ),*) {
fn show(&self) -> String {
let arr = vec![self.$idx.show(), $(self.$nidx.show(), ) *];
format!("({})", arr.join(", "))
}
}
}
}
tuple_impls! {
(20 => U),
(19 => T),
(18 => S),
(17 => R),
(16 => Q),
(15 => P),
(14 => O),
(13 => N),
(12 => M),
(11 => L),
(10 => K),
(9 => J),
(8 => I),
(7 => H),
(6 => G),
(5 => F),
(4 => E),
(3 => D),
(2 => C),
(1 => B),
(0 => A),
}
#[cfg(test)]
mod tests {
use std::cell::*;
use super::Show;
use std::rc::Rc;
use std::sync::Arc;
use std::collections::{HashSet, HashMap};
macro_rules! simple_show_tests {
($($x: expr; $tr:ty; $name:ident),+) => {
$(
#[test]
fn $name() {
let i: $tr = $x;
assert_eq!(i.show(), $x.to_string())
}
)*
}
}
simple_show_tests!(
1; i8; test_i8,
1; i16; test_i16,
1; i32; test_i32,
1; i64; test_i64,
1; u8; test_u8,
1; u16; test_u16,
1; u32; test_u32,
1; u64; test_u64,
1; usize; test_usize,
1; isize; test_isize,
1f32; f32; test_f32,
1f64; f64; test_f64,
true; bool; test_bool
);
#[test]
fn test_str() {
let i = "hello";
assert_eq!(i.show(), "\"hello\"")
}
#[test]
fn test_char() {
let i: char = 't';
assert_eq!(i.show(), "'t'")
}
#[test]
fn test_string() {
let mut i = String::new();
i.push_str("hello");
assert_eq!(i.show(), "\"hello\"")
}
#[test]
fn test_tuple() {
let i = (1, 'a', 1.3f32, "hello");
assert_eq!(i.show(), "(1, 'a', 1.3, \"hello\")")
}
#[test]
fn test_slice() {
let i = ["hello", "world"];
assert_eq!(i.show(), "[\"hello\", \"world\"]")
}
#[test]
fn test_vec() {
let i = vec!["hello", "world"];
assert_eq!(i.show(), "[\"hello\", \"world\"]")
}
#[test]
fn test_unit() {
let i = ();
assert_eq!(i.show(), "()")
}
#[test]
fn test_some() {
let i = Some("one");
assert_eq!(i.show(), "Some(\"one\")")
}
#[test]
fn test_none() {
let i: Option<i8> = None;
assert_eq!(i.show(), "None")
}
#[test]
fn test_box() {
let i = Box::new(1);
assert_eq!(i.show(), "Box(1)");
assert_eq!(Some(Box::new(1)).show(), "Some(Box(1))");
}
#[test]
fn test_cell() {
let i = Cell::new(1);
assert_eq!(i.show(), "1")
}
#[test]
fn test_refcell() {
let i = RefCell::new(1);
assert_eq!(i.show(), "RefCell(value=1)")
}
#[test]
fn test_rc() {
let i = Rc::new(1);
assert_eq!(i.show(), "1")
}
#[test]
fn test_arc() {
let i = Arc::new(1);
assert_eq!(i.show(), "1")
}
#[test]
fn test_hashset() {
let mut i = HashSet::new();
i.insert("hello");
i.insert("world");
let shown = i.show();
assert!(shown.contains("HashSet("));
assert!(shown.contains("\"hello\""));
assert!(shown.contains("\"world\""));
}
#[test]
fn test_hashmap() {
let mut i: HashMap<i8, bool> = HashMap::new();
i.insert(1, true);
i.insert(2, false);
let shown = i.show();
assert!(shown.contains("HashMap("));
assert!(shown.contains("1 -> true"));
assert!(shown.contains("2 -> false"));
}
}