/*! Assorted helpers */ use std::rc::Rc; use crate::float_ord::FloatOrd; use std::borrow::Borrow; use std::cmp::{Ordering, PartialOrd}; use std::hash::{ Hash, Hasher }; use std::ops::Mul; pub mod c { use super::*; use std::cell::RefCell; use std::ffi::{ CStr, CString }; use std::os::raw::c_char; use std::rc::Rc; use std::str::Utf8Error; use std::sync::{Arc, Mutex}; // traits use std::borrow::ToOwned; // The lifetime on input limits the existence of the result pub fn as_str(s: &*const c_char) -> Result, Utf8Error> { if s.is_null() { Ok(None) } else { unsafe {CStr::from_ptr(*s)} .to_str() .map(Some) } } pub fn as_cstr(s: &*const c_char) -> Option<&CStr> { if s.is_null() { None } else { Some(unsafe {CStr::from_ptr(*s)}) } } pub fn into_cstring(s: *const c_char) -> Result, std::ffi::NulError> { if s.is_null() { Ok(None) } else { CString::new( unsafe {CStr::from_ptr(s)}.to_bytes() ).map(Some) } } #[cfg(test)] mod tests { use super::*; use std::ptr; #[test] fn test_null_cstring() { assert_eq!(into_cstring(ptr::null()), Ok(None)) } #[test] fn test_null_str() { assert_eq!(as_str(&ptr::null()), Ok(None)) } } /// Marker trait for values that can be transferred to/received from C. /// They must be either *const or *mut or repr(transparent). pub trait COpaquePtr {} /// Wraps structures to pass them safely to/from C /// Since C doesn't respect borrowing rules, /// RefCell will enforce them dynamically (only 1 writer/many readers) /// Rc is implied and will ensure timely dropping #[repr(transparent)] pub struct Wrapped(*const RefCell); // It would be nice to implement `Borrow` // directly on the raw pointer to avoid one conversion call, // but the `borrow()` call needs to extract a `Rc`, // and at the same time return a reference to it (`std::cell::Ref`) // to take advantage of `Rc::borrow()` runtime checks. // Unfortunately, that needs a `Ref` struct with self-referential fields, // which is a bit too complex for now. impl Wrapped { pub fn new(value: T) -> Wrapped { Wrapped::wrap(Rc::new(RefCell::new(value))) } pub fn wrap(state: Rc>) -> Wrapped { Wrapped(Rc::into_raw(state)) } /// Extracts the reference to the data. /// It may cause problems if attempted in more than one place pub unsafe fn unwrap(self) -> Rc> { Rc::from_raw(self.0) } /// Creates a new Rc reference to the same data. /// Use for accessing the underlying data as a reference. pub fn clone_ref(&self) -> Rc> { // A bit dangerous: the Rc may be in use elsewhere let used_rc = unsafe { Rc::from_raw(self.0) }; let rc = used_rc.clone(); Rc::into_raw(used_rc); // prevent dropping the original reference rc } } impl Clone for Wrapped { fn clone(&self) -> Wrapped { Wrapped::wrap(self.clone_ref()) } } /// ToOwned won't work here /// because it's really difficult to implement Borrow on Wrapped /// with the Rc> chain on the way to the data impl CloneOwned for Wrapped { type Owned = T; fn clone_owned(&self) -> T { let rc = self.clone_ref(); let r = RefCell::borrow(&rc); r.to_owned() } } impl COpaquePtr for Wrapped {} /// Similar to Wrapped, except thread-safe. #[repr(transparent)] pub struct ArcWrapped(*const Mutex); impl ArcWrapped { pub fn new(value: T) -> Self { Self::wrap(Arc::new(Mutex::new(value))) } pub fn wrap(state: Arc>) -> Self { Self(Arc::into_raw(state)) } /// Extracts the reference to the data. /// It may cause problems if attempted in more than one place pub unsafe fn unwrap(self) -> Arc> { Arc::from_raw(self.0) } /// Creates a new Rc reference to the same data. /// Use for accessing the underlying data as a reference. pub fn clone_ref(&self) -> Arc> { // A bit dangerous: the Rc may be in use elsewhere let used_rc = unsafe { Arc::from_raw(self.0) }; let rc = used_rc.clone(); let _ = Arc::into_raw(used_rc); // prevent dropping the original reference rc } } impl Clone for ArcWrapped { fn clone(&self) -> Self { Self::wrap(self.clone_ref()) } } /// ToOwned won't work here impl CloneOwned for ArcWrapped { type Owned = T; fn clone_owned(&self) -> T { let rc = self.clone_ref(); // FIXME: this panic here is inelegant. // It will only happen in case of crashes elsewhere, but still. let r = rc.lock().unwrap(); r.to_owned() } } } /// Clones the underlying data structure, like ToOwned. pub trait CloneOwned { type Owned; fn clone_owned(&self) -> Self::Owned; } pub fn find_max_double(iterator: I, get: F) -> f64 where I: Iterator, F: Fn(&T) -> f64 { iterator.map(|value| FloatOrd(get(&value))) .max().unwrap_or(FloatOrd(0f64)) .0 } pub trait DivCeil { type Output; fn div_ceil(self, rhs: Rhs) -> Self::Output; } /// Newer Rust introduces this natively, /// but we don't always have newer Rust. impl DivCeil for i32 { type Output = Self; fn div_ceil(self, other: i32) -> Self::Output { let d = self / other; let m = self % other; if m == 0 { d } else { d + 1} } } #[derive(Debug, Clone, Copy)] pub struct Rational { pub numerator: T, pub denominator: u32, } impl> Rational { pub fn ceil(self) -> U { self.numerator.div_ceil(self.denominator as i32) } } impl> Mul for Rational { type Output = Self; fn mul(self, m: i32) -> Self { Self { numerator: self.numerator * m, denominator: self.denominator, } } } impl> Mul> for Rational { type Output = Self; fn mul(self, m: Rational) -> Self { Self { numerator: self.numerator * m.numerator, denominator: self.denominator * m.denominator, } } } impl PartialEq for Rational { fn eq(&self, other: &Self) -> bool { (self.denominator as i64).saturating_mul(other.numerator as i64) == (other.denominator as i64).saturating_mul(self.numerator as i64) } } impl Eq for Rational {} impl Ord for Rational { fn cmp(&self, other: &Self) -> Ordering { // Using 64-bit values to make overflows unlikely. // If i32_max * u32_max can exceed i64_max, // then this is actually PartialOrd. // Saturating mul used just to avoid propagating mistakes. (other.denominator as i64).saturating_mul(self.numerator as i64) .cmp( &(self.denominator as i64).saturating_mul(other.numerator as i64) ) } } impl PartialOrd for Rational { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } /// Compares pointers but not internal values of Rc pub struct Pointer(pub Rc); impl Pointer { pub fn new(value: T) -> Self { Pointer(Rc::new(value)) } } impl Hash for Pointer { fn hash(&self, state: &mut H) { (&*self.0 as *const T).hash(state); } } impl PartialEq for Pointer { fn eq(&self, other: &Pointer) -> bool { Rc::ptr_eq(&self.0, &other.0) } } impl Eq for Pointer {} impl Clone for Pointer { fn clone(&self) -> Self { Pointer(self.0.clone()) } } impl Borrow> for Pointer { fn borrow(&self) -> &Rc { &self.0 } } pub trait WarningHandler { /// Handle a warning fn handle(&mut self, warning: &str); } /// Removes the first matching item pub fn vec_remove bool>(v: &mut Vec, pred: F) -> Option { let idx = v.iter().position(pred); idx.map(|idx| v.remove(idx)) } /// Repeats all the items of the iterator forever, /// but returns the cycle number alongside. /// Inefficient due to all the vectors, but doesn't have to be fast. pub fn cycle_count>(iter: I) -> impl Iterator { let numbered_copies = vec![iter].into_iter() .cycle() .enumerate(); numbered_copies.flat_map(|(idx, cycle)| // Pair each element from the cycle with a copy of the index. cycle.zip( vec![idx].into_iter().cycle() // Repeat the index forever. ) ) } #[cfg(test)] mod tests { use super::*; use std::collections::HashSet; #[test] fn check_set() { let mut s = HashSet::new(); let first = Rc::new(1u32); s.insert(Pointer(first.clone())); assert_eq!(s.insert(Pointer(Rc::new(2u32))), true); assert_eq!(s.remove(&Pointer(first)), true); } #[test] fn check_count() { assert_eq!( cycle_count(5..8).take(7).collect::>(), vec![(5, 0), (6, 0), (7, 0), (5, 1), (6, 1), (7, 1), (5, 2)] ); } #[test] fn check_rational_cmp() { assert_eq!( Rational { numerator: 1, denominator: 1 }, Rational { numerator: 1, denominator: 1 }, ); assert_eq!( Rational { numerator: 1, denominator: 1 }, Rational { numerator: 2, denominator: 2 }, ); assert!( Rational { numerator: 1, denominator: 1 } < Rational { numerator: 2, denominator: 1 } ); } }