|
#![feature(core)] |
|
|
|
use std::fmt; |
|
use std::iter; |
|
use std::marker::MarkerTrait; |
|
use std::num::{Int}; |
|
|
|
trait AsByte { |
|
fn as_u8(&self) -> u8; |
|
fn as_i8(&self) -> i8; |
|
fn not_less_than_zero(&self) -> bool; |
|
fn less_than_256(&self) -> bool; |
|
fn less_than_128(&self) -> bool; |
|
fn not_less_than_neg128(&self) -> bool; |
|
fn value_falls_in_i8_range(&self) -> bool { |
|
self.not_less_than_neg128() && self.less_than_128() |
|
} |
|
fn value_falls_in_u8_range(&self) -> bool { |
|
self.not_less_than_zero() && self.less_than_256() |
|
} |
|
fn value_falls_in_i8_or_u8_range(&self) -> bool { |
|
self.not_less_than_neg128() && self.less_than_256() |
|
} |
|
} |
|
|
|
trait IntTypeInfo { |
|
fn signed_bit_width() -> (bool, u32); |
|
fn type_is_signed() -> bool { Self::signed_bit_width().0 } |
|
fn bit_width() -> u32 { Self::signed_bit_width().1 } |
|
fn zero_after_rshift(&self, rhs: u32) -> bool; |
|
fn ones_after_rshift(&self, rhs: u32) -> bool; |
|
fn same_after_rshift(&self, rhs: u32) -> bool { |
|
self.zero_after_rshift(rhs) || self.ones_after_rshift(rhs) |
|
} |
|
fn signbits(&self) -> Self; |
|
} |
|
impl IntTypeInfo for i8 { |
|
fn signed_bit_width() -> (bool, u32) { (true, 8) } |
|
fn signbits(&self) -> Self { |
|
if *self < 0 { -1 } else { 0 } |
|
} |
|
fn zero_after_rshift(&self, rhs: u32) -> bool { (*self >> rhs) == 0 } |
|
fn ones_after_rshift(&self, rhs: u32) -> bool { (*self >> rhs) == -1 } |
|
} |
|
impl IntTypeInfo for i16 { |
|
fn signed_bit_width() -> (bool, u32) { (true, 16) } |
|
fn signbits(&self) -> Self { |
|
if *self < 0 { -1 } else { 0 } |
|
} |
|
fn zero_after_rshift(&self, rhs: u32) -> bool { (*self >> rhs) == 0 } |
|
fn ones_after_rshift(&self, rhs: u32) -> bool { (*self >> rhs) == -1 } |
|
} |
|
impl IntTypeInfo for u8 { |
|
fn signed_bit_width() -> (bool, u32) { (false, 8) } |
|
fn signbits(&self) -> Self { 0 } |
|
fn zero_after_rshift(&self, rhs: u32) -> bool { (*self >> rhs) == 0 } |
|
fn ones_after_rshift(&self, rhs: u32) -> bool { (*self >> rhs) == -1 } |
|
} |
|
impl IntTypeInfo for u16 { |
|
fn signed_bit_width() -> (bool, u32) { (false, 16) } |
|
fn signbits(&self) -> Self { 0 } |
|
fn zero_after_rshift(&self, rhs: u32) -> bool { (*self >> rhs) == 0 } |
|
fn ones_after_rshift(&self, rhs: u32) -> bool { (*self >> rhs) == -1 } |
|
} |
|
|
|
impl AsByte for i8 { |
|
fn as_u8(&self) -> u8 { *self as u8 } |
|
fn as_i8(&self) -> i8 { *self } |
|
fn less_than_128(&self) -> bool { true } |
|
fn less_than_256(&self) -> bool { true } |
|
fn not_less_than_zero(&self) -> bool { *self >= 0 } |
|
fn not_less_than_neg128(&self) -> bool { true } |
|
} |
|
|
|
impl AsByte for u8 { |
|
fn as_u8(&self) -> u8 { *self } |
|
fn as_i8(&self) -> i8 { *self as i8 } |
|
fn less_than_128(&self) -> bool { *self < 0x80 } |
|
fn less_than_256(&self) -> bool { true } |
|
fn not_less_than_zero(&self) -> bool { true } |
|
fn not_less_than_neg128(&self) -> bool { true } |
|
} |
|
|
|
impl AsByte for i16 { |
|
fn as_u8(&self) -> u8 { *self as u8 } |
|
fn as_i8(&self) -> i8 { *self as i8 } |
|
fn less_than_128(&self) -> bool { *self < 0x80 } |
|
fn less_than_256(&self) -> bool { *self < 0x100 } |
|
fn not_less_than_zero(&self) -> bool { *self >= 0 } |
|
fn not_less_than_neg128(&self) -> bool { *self >= -128 } |
|
} |
|
|
|
impl AsByte for u16 { |
|
fn as_u8(&self) -> u8 { *self as u8 } |
|
fn as_i8(&self) -> i8 { *self as i8 } |
|
fn less_than_128(&self) -> bool { *self < 0x80 } |
|
fn less_than_256(&self) -> bool { *self < 0x100 } |
|
fn not_less_than_zero(&self) -> bool { true } |
|
fn not_less_than_neg128(&self) -> bool { true } |
|
} |
|
|
|
struct WidthOriented<T>(T); |
|
struct StrictRange<T>(T); |
|
struct LooseRange<T>(T); |
|
|
|
trait NumType: MarkerTrait { fn name() -> &'static str; } |
|
impl NumType for i8 { fn name() -> &'static str { "i8" } } |
|
impl NumType for u8 { fn name() -> &'static str { "u8" } } |
|
impl NumType for i16 { fn name() -> &'static str { "i16" } } |
|
impl NumType for u16 { fn name() -> &'static str { "u16" } } |
|
|
|
impl<T:NumType+fmt::LowerHex> fmt::Debug for WidthOriented<T> { |
|
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { |
|
write!(w, "WidthOriented(0x{:x}_{})", self.0, T::name()) |
|
} |
|
} |
|
impl<T:NumType+fmt::LowerHex> fmt::Debug for StrictRange<T> { |
|
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { |
|
write!(w, "StrictRange(0x{:x}_{})", self.0, T::name()) |
|
} |
|
} |
|
impl<T:NumType+fmt::LowerHex> fmt::Debug for LooseRange<T> { |
|
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { |
|
write!(w, "LooseRange(0x{:x}_{})", self.0, T::name()) |
|
} |
|
} |
|
|
|
trait CheckedAsByte : AsByte { |
|
fn checked_as_u8(&self) -> Option<u8>; |
|
fn checked_as_i8(&self) -> Option<i8>; |
|
} |
|
|
|
impl<T:AsByte> AsByte for WidthOriented<T> { |
|
fn as_u8(&self) -> u8 { self.0.as_u8() } |
|
fn as_i8(&self) -> i8 { self.0.as_i8() } |
|
fn less_than_128(&self) -> bool{ self.0.less_than_128() } |
|
fn less_than_256(&self) -> bool{ self.0.less_than_256() } |
|
fn not_less_than_zero(&self) -> bool{ self.0.not_less_than_zero() } |
|
fn not_less_than_neg128(&self) -> bool { self.0.not_less_than_neg128() } |
|
} |
|
|
|
impl<T:AsByte> AsByte for StrictRange<T> { |
|
fn as_u8(&self) -> u8 { self.0.as_u8() } |
|
fn as_i8(&self) -> i8 { self.0.as_i8() } |
|
fn less_than_128(&self) -> bool{ self.0.less_than_128() } |
|
fn less_than_256(&self) -> bool{ self.0.less_than_256() } |
|
fn not_less_than_zero(&self) -> bool{ self.0.not_less_than_zero() } |
|
fn not_less_than_neg128(&self) -> bool{ self.0.not_less_than_neg128() } |
|
} |
|
|
|
impl<T:AsByte> AsByte for LooseRange<T> { |
|
fn as_u8(&self) -> u8 { self.0.as_u8() } |
|
fn as_i8(&self) -> i8 { self.0.as_i8() } |
|
fn less_than_128(&self) -> bool{ self.0.less_than_128() } |
|
fn less_than_256(&self) -> bool{ self.0.less_than_256() } |
|
fn not_less_than_zero(&self) -> bool{ self.0.not_less_than_zero() } |
|
fn not_less_than_neg128(&self) -> bool{ self.0.not_less_than_neg128() } |
|
} |
|
|
|
impl<T:Int+IntTypeInfo+AsByte+fmt::Debug> CheckedAsByte for WidthOriented<T> { |
|
fn checked_as_u8(&self) -> Option<u8> { |
|
if T::bit_width() == 8 || self.value_falls_in_u8_range() { |
|
Some(self.as_u8()) |
|
} else { |
|
None |
|
} |
|
} |
|
fn checked_as_i8(&self) -> Option<i8> { |
|
if T::bit_width() == 8 || self.value_falls_in_i8_range() { |
|
Some(self.as_i8()) |
|
} else { |
|
None |
|
} |
|
} |
|
} |
|
|
|
impl<T:Int+AsByte> CheckedAsByte for StrictRange<T> { |
|
fn checked_as_u8(&self) -> Option<u8> { |
|
if self.value_falls_in_u8_range() { Some(self.as_u8()) } else { None } |
|
} |
|
fn checked_as_i8(&self) -> Option<i8> { |
|
if self.value_falls_in_i8_range() { Some(self.as_i8()) } else { None } |
|
} |
|
} |
|
|
|
impl<T:Int+AsByte> CheckedAsByte for LooseRange<T> { |
|
fn checked_as_u8(&self) -> Option<u8> { |
|
if self.value_falls_in_i8_or_u8_range() { Some(self.as_u8()) } else { None } |
|
} |
|
fn checked_as_i8(&self) -> Option<i8> { |
|
if self.value_falls_in_i8_or_u8_range() { Some(self.as_i8()) } else { None } |
|
} |
|
} |
|
|
|
fn fill_left<T:fmt::Debug>(x: T, fill: usize) -> String { |
|
let s = format!("{:?}", x); |
|
if s.len() >= fill { |
|
s |
|
} else { |
|
let indent = fill - s.len(); |
|
let indent: String = iter::repeat(' ').take(indent).collect(); |
|
indent + &s |
|
} |
|
} |
|
|
|
trait Results<T>: CheckedAsByte + fmt::Debug { |
|
fn inner(&self) -> T; |
|
fn results(&self) -> (T, String, i8, String, u8, String) { |
|
let i = self; |
|
(i.inner(), fill_left(self, 25), |
|
i.as_i8(), fill_left(i.checked_as_i8(), 10), |
|
i.as_u8(), fill_left(i.checked_as_u8(), 10)) |
|
} |
|
|
|
} |
|
|
|
impl<T> Results<T> for WidthOriented<T> |
|
where T:Copy+NumType+fmt::LowerHex, WidthOriented<T> : CheckedAsByte { |
|
fn inner(&self) -> T { self.0 } |
|
} |
|
|
|
impl<T> Results<T> for StrictRange<T> |
|
where T:Copy+NumType+fmt::LowerHex, StrictRange<T> : CheckedAsByte { |
|
fn inner(&self) -> T { self.0 } |
|
} |
|
|
|
impl<T> Results<T> for LooseRange<T> |
|
where T:Copy+NumType+fmt::LowerHex, LooseRange<T> : CheckedAsByte { |
|
fn inner(&self) -> T { self.0 } |
|
} |
|
|
|
fn main() { |
|
let inputs = [0, 1, 0x7F]; |
|
println!("TRIVIAL CASES"); |
|
for &j in &inputs { |
|
test_input(j); |
|
} |
|
println!("NONOBVIOUS CASES"); |
|
let inputs = [0xFF, 0x80, 129, 0x100, 0x7FFF, 0x8000, 0xFFFF]; |
|
for &j in &inputs { |
|
test_input(j); |
|
} |
|
|
|
macro_rules! row { |
|
() => { "{:>25} {:>6} {:>5} {:>10} {:>5} {:>10} " } |
|
} |
|
|
|
fn test_input(j: i32) { |
|
println!("{:>25} {:>6} ({:>5},{:>10}) ({:>5},{:>10})", |
|
"OFLO_HANDLER", "INPUT", "as i8", "checked", "as u8","checked"); |
|
println!(row!(), |
|
"------------", "------", "-----", "--------", "-----","--------"); |
|
let i = StrictRange(j as i8); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
let i = WidthOriented( j as i8); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
let i = LooseRange(j as i8); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
println!(""); |
|
let i = StrictRange(j as u8); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
let i = WidthOriented( j as u8); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
let i = LooseRange(j as u8); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
println!(""); |
|
let i = StrictRange(j as i16); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
let i = WidthOriented( j as i16); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
let i = LooseRange(j as i16); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
println!(""); |
|
let i = StrictRange(j as u16); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
let i = WidthOriented( j as u16); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
let i = LooseRange(j as u16); let r = i.results(); |
|
println!(row!(), r.1, r.0, r.2, r.3, r.4, r.5); |
|
println!(""); |
|
} |
|
} |
This comment has been minimized.
pnkfelix commentedMar 12, 2015
linked from:
https://gist.github.com/pnkfelix/d3d97ed0f6a945e24a7a