1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
//! Module containing various utility functions. use num_traits::{CheckedShr, PrimInt, Num}; /// Limit the specified number to be at most the specified bit-width /// /// # Examples /// /// ``` /// # use pir_8_emu::util::limit_to_width; /// assert_eq!(limit_to_width(0b0101, 3), Some(0b0101)); /// /// assert_eq!(limit_to_width(0b1010, 3), None); /// ``` pub fn limit_to_width<T: Num + PrimInt + CheckedShr>(number: T, bit_width: u8) -> Option<T> { if number.checked_shr(bit_width.into()).unwrap_or_else(T::zero) != T::zero() { None } else { Some(number) } } /// Limit the specified number to be at most the specified bit-width /// /// # Examples /// /// ``` /// # use pir_8_emu::util::min_byte_width; /// assert_eq!(min_byte_width(0x0F), 1); /// assert_eq!(min_byte_width(0x010F), 2); /// assert_eq!(min_byte_width(0x00F0010F), 4); /// ``` pub fn min_byte_width<T: Num + PrimInt + CheckedShr>(number: T) -> u8 { let mut cur_bytes = 1; while number.checked_shr(8 * cur_bytes).unwrap_or_else(T::zero) != T::zero() { cur_bytes *= 2; } cur_bytes as u8 } /// Parse a number from the specified string, automatically detecting the base prefix. /// /// # Examples /// /// ``` /// # use pir_8_emu::util::parse_with_prefix; /// assert_eq!(parse_with_prefix::<u16>("0x0420"), Some(0x0420)); /// assert_eq!(parse_with_prefix::<u16>("0o0420"), Some(0o0420)); /// assert_eq!(parse_with_prefix::<u16>("0B0101"), Some(0b0101)); /// /// assert_eq!(parse_with_prefix::<u16>("0b1010_0101"), Some(0b1010_0101)); /// /// assert_eq!(parse_with_prefix::<u16>("0"), Some(0)); /// /// assert_eq!(parse_with_prefix::<u16>("0x2OOM"), None); /// ``` pub fn parse_with_prefix<T: Num + PrimInt>(from: &str) -> Option<T> { let mut cc = from.chars(); let (radix, depth) = if cc.next()? == '0' { match cc.next() { Some('x') | Some('X') => (16, 2), Some('o') | Some('O') => (8, 2), Some('b') | Some('B') => (2, 2), Some(_) => (10, 0), None => return Some(T::zero()), } } else { (10, 0) }; if from.contains('_') { T::from_str_radix(&from[depth..].replace('_', ""), radix).ok() } else { T::from_str_radix(&from[depth..], radix).ok() } } /// Strip off all data starting with the specified character, if exists /// /// # Examples /// /// ``` /// # use pir_8_emu::util::remove_comment; /// assert_eq!(remove_comment(';', "UwU ; OwO"), "UwU "); /// /// assert_eq!(remove_comment(';', "yeehaw"), "yeehaw"); /// ``` pub fn remove_comment(comment_char: char, from: &str) -> &str { match from.find(comment_char) { Some(idx) => &from[0..idx], None => from, } }