Skip to content

Instantly share code, notes, and snippets.

@pnkfelix
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pnkfelix/4db827b355c737a93576 to your computer and use it in GitHub Desktop.
Save pnkfelix/4db827b355c737a93576 to your computer and use it in GitHub Desktop.
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
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment