Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Demo of various semantics for checked overflow
NONOBVIOUS CASES
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0xff_i8) -1 -1 Some(-1) 255 None
WidthOriented(0xff_i8) -1 -1 Some(-1) 255 Some(255)
LooseRange(0xff_i8) -1 -1 Some(-1) 255 Some(255)
StrictRange(0xff_u8) 255 -1 None 255 Some(255)
WidthOriented(0xff_u8) 255 -1 Some(-1) 255 Some(255)
LooseRange(0xff_u8) 255 -1 Some(-1) 255 Some(255)
StrictRange(0xff_i16) 255 -1 None 255 Some(255)
WidthOriented(0xff_i16) 255 -1 None 255 Some(255)
LooseRange(0xff_i16) 255 -1 Some(-1) 255 Some(255)
StrictRange(0xff_u16) 255 -1 None 255 Some(255)
WidthOriented(0xff_u16) 255 -1 None 255 Some(255)
LooseRange(0xff_u16) 255 -1 Some(-1) 255 Some(255)
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0x80_i8) -128 -128 Some(-128) 128 None
WidthOriented(0x80_i8) -128 -128 Some(-128) 128 Some(128)
LooseRange(0x80_i8) -128 -128 Some(-128) 128 Some(128)
StrictRange(0x80_u8) 128 -128 None 128 Some(128)
WidthOriented(0x80_u8) 128 -128 Some(-128) 128 Some(128)
LooseRange(0x80_u8) 128 -128 Some(-128) 128 Some(128)
StrictRange(0x80_i16) 128 -128 None 128 Some(128)
WidthOriented(0x80_i16) 128 -128 None 128 Some(128)
LooseRange(0x80_i16) 128 -128 Some(-128) 128 Some(128)
StrictRange(0x80_u16) 128 -128 None 128 Some(128)
WidthOriented(0x80_u16) 128 -128 None 128 Some(128)
LooseRange(0x80_u16) 128 -128 Some(-128) 128 Some(128)
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0x81_i8) -127 -127 Some(-127) 129 None
WidthOriented(0x81_i8) -127 -127 Some(-127) 129 Some(129)
LooseRange(0x81_i8) -127 -127 Some(-127) 129 Some(129)
StrictRange(0x81_u8) 129 -127 None 129 Some(129)
WidthOriented(0x81_u8) 129 -127 Some(-127) 129 Some(129)
LooseRange(0x81_u8) 129 -127 Some(-127) 129 Some(129)
StrictRange(0x81_i16) 129 -127 None 129 Some(129)
WidthOriented(0x81_i16) 129 -127 None 129 Some(129)
LooseRange(0x81_i16) 129 -127 Some(-127) 129 Some(129)
StrictRange(0x81_u16) 129 -127 None 129 Some(129)
WidthOriented(0x81_u16) 129 -127 None 129 Some(129)
LooseRange(0x81_u16) 129 -127 Some(-127) 129 Some(129)
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0x0_i8) 0 0 Some(0) 0 Some(0)
WidthOriented(0x0_i8) 0 0 Some(0) 0 Some(0)
LooseRange(0x0_i8) 0 0 Some(0) 0 Some(0)
StrictRange(0x0_u8) 0 0 Some(0) 0 Some(0)
WidthOriented(0x0_u8) 0 0 Some(0) 0 Some(0)
LooseRange(0x0_u8) 0 0 Some(0) 0 Some(0)
StrictRange(0x100_i16) 256 0 None 0 None
WidthOriented(0x100_i16) 256 0 None 0 None
LooseRange(0x100_i16) 256 0 None 0 None
StrictRange(0x100_u16) 256 0 None 0 None
WidthOriented(0x100_u16) 256 0 None 0 None
LooseRange(0x100_u16) 256 0 None 0 None
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0xff_i8) -1 -1 Some(-1) 255 None
WidthOriented(0xff_i8) -1 -1 Some(-1) 255 Some(255)
LooseRange(0xff_i8) -1 -1 Some(-1) 255 Some(255)
StrictRange(0xff_u8) 255 -1 None 255 Some(255)
WidthOriented(0xff_u8) 255 -1 Some(-1) 255 Some(255)
LooseRange(0xff_u8) 255 -1 Some(-1) 255 Some(255)
StrictRange(0x7fff_i16) 32767 -1 None 255 None
WidthOriented(0x7fff_i16) 32767 -1 None 255 None
LooseRange(0x7fff_i16) 32767 -1 None 255 None
StrictRange(0x7fff_u16) 32767 -1 None 255 None
WidthOriented(0x7fff_u16) 32767 -1 None 255 None
LooseRange(0x7fff_u16) 32767 -1 None 255 None
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0x0_i8) 0 0 Some(0) 0 Some(0)
WidthOriented(0x0_i8) 0 0 Some(0) 0 Some(0)
LooseRange(0x0_i8) 0 0 Some(0) 0 Some(0)
StrictRange(0x0_u8) 0 0 Some(0) 0 Some(0)
WidthOriented(0x0_u8) 0 0 Some(0) 0 Some(0)
LooseRange(0x0_u8) 0 0 Some(0) 0 Some(0)
StrictRange(0x8000_i16) -32768 0 None 0 None
WidthOriented(0x8000_i16) -32768 0 None 0 None
LooseRange(0x8000_i16) -32768 0 None 0 None
StrictRange(0x8000_u16) 32768 0 None 0 None
WidthOriented(0x8000_u16) 32768 0 None 0 None
LooseRange(0x8000_u16) 32768 0 None 0 None
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0xff_i8) -1 -1 Some(-1) 255 None
WidthOriented(0xff_i8) -1 -1 Some(-1) 255 Some(255)
LooseRange(0xff_i8) -1 -1 Some(-1) 255 Some(255)
StrictRange(0xff_u8) 255 -1 None 255 Some(255)
WidthOriented(0xff_u8) 255 -1 Some(-1) 255 Some(255)
LooseRange(0xff_u8) 255 -1 Some(-1) 255 Some(255)
StrictRange(0xffff_i16) -1 -1 Some(-1) 255 None
WidthOriented(0xffff_i16) -1 -1 Some(-1) 255 None
LooseRange(0xffff_i16) -1 -1 Some(-1) 255 Some(255)
StrictRange(0xffff_u16) 65535 -1 None 255 None
WidthOriented(0xffff_u16) 65535 -1 None 255 None
LooseRange(0xffff_u16) 65535 -1 None 255 None
TRIVIAL CASES
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0x0_i8) 0 0 Some(0) 0 Some(0)
WidthOriented(0x0_i8) 0 0 Some(0) 0 Some(0)
LooseRange(0x0_i8) 0 0 Some(0) 0 Some(0)
StrictRange(0x0_u8) 0 0 Some(0) 0 Some(0)
WidthOriented(0x0_u8) 0 0 Some(0) 0 Some(0)
LooseRange(0x0_u8) 0 0 Some(0) 0 Some(0)
StrictRange(0x0_i16) 0 0 Some(0) 0 Some(0)
WidthOriented(0x0_i16) 0 0 Some(0) 0 Some(0)
LooseRange(0x0_i16) 0 0 Some(0) 0 Some(0)
StrictRange(0x0_u16) 0 0 Some(0) 0 Some(0)
WidthOriented(0x0_u16) 0 0 Some(0) 0 Some(0)
LooseRange(0x0_u16) 0 0 Some(0) 0 Some(0)
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0x1_i8) 1 1 Some(1) 1 Some(1)
WidthOriented(0x1_i8) 1 1 Some(1) 1 Some(1)
LooseRange(0x1_i8) 1 1 Some(1) 1 Some(1)
StrictRange(0x1_u8) 1 1 Some(1) 1 Some(1)
WidthOriented(0x1_u8) 1 1 Some(1) 1 Some(1)
LooseRange(0x1_u8) 1 1 Some(1) 1 Some(1)
StrictRange(0x1_i16) 1 1 Some(1) 1 Some(1)
WidthOriented(0x1_i16) 1 1 Some(1) 1 Some(1)
LooseRange(0x1_i16) 1 1 Some(1) 1 Some(1)
StrictRange(0x1_u16) 1 1 Some(1) 1 Some(1)
WidthOriented(0x1_u16) 1 1 Some(1) 1 Some(1)
LooseRange(0x1_u16) 1 1 Some(1) 1 Some(1)
OFLO_HANDLER INPUT (as i8, checked) (as u8, checked)
------------ ------ ----- -------- ----- --------
StrictRange(0x7f_i8) 127 127 Some(127) 127 Some(127)
WidthOriented(0x7f_i8) 127 127 Some(127) 127 Some(127)
LooseRange(0x7f_i8) 127 127 Some(127) 127 Some(127)
StrictRange(0x7f_u8) 127 127 Some(127) 127 Some(127)
WidthOriented(0x7f_u8) 127 127 Some(127) 127 Some(127)
LooseRange(0x7f_u8) 127 127 Some(127) 127 Some(127)
StrictRange(0x7f_i16) 127 127 Some(127) 127 Some(127)
WidthOriented(0x7f_i16) 127 127 Some(127) 127 Some(127)
LooseRange(0x7f_i16) 127 127 Some(127) 127 Some(127)
StrictRange(0x7f_u16) 127 127 Some(127) 127 Some(127)
WidthOriented(0x7f_u16) 127 127 Some(127) 127 Some(127)
LooseRange(0x7f_u16) 127 127 Some(127) 127 Some(127)
#![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!("");
}
}
@pnkfelix

This comment has been minimized.

Copy link
Owner Author

pnkfelix commented Mar 12, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.