|  | pub(crate) trait ForceAdd: Sized { | 
|  | fn force_add(self, rhs: Self) -> Self; | 
|  | } | 
|  |  | 
|  | impl ForceAdd for u8 { | 
|  | fn force_add(self, rhs: Self) -> Self { | 
|  | self.checked_add(rhs).unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ForceAdd for i32 { | 
|  | fn force_add(self, rhs: Self) -> Self { | 
|  | self.checked_add(rhs).unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ForceAdd for u32 { | 
|  | fn force_add(self, rhs: Self) -> Self { | 
|  | self.checked_add(rhs).unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ForceAdd for u64 { | 
|  | fn force_add(self, rhs: Self) -> Self { | 
|  | self.checked_add(rhs).unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ForceAdd for usize { | 
|  | fn force_add(self, rhs: Self) -> Self { | 
|  | self.checked_add(rhs).unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) trait ForceMul: Sized { | 
|  | fn force_mul(self, rhs: Self) -> Self; | 
|  | } | 
|  |  | 
|  | impl ForceMul for i32 { | 
|  | fn force_mul(self, rhs: Self) -> Self { | 
|  | self.checked_mul(rhs).unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ForceMul for i64 { | 
|  | fn force_mul(self, rhs: Self) -> Self { | 
|  | self.checked_mul(rhs).unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl ForceMul for u64 { | 
|  | fn force_mul(self, rhs: Self) -> Self { | 
|  | self.checked_mul(rhs).unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) trait ForceInto { | 
|  | fn force_into<U>(self) -> U | 
|  | where | 
|  | Self: TryInto<U>; | 
|  | } | 
|  |  | 
|  | impl<T> ForceInto for T { | 
|  | fn force_into<U>(self) -> U | 
|  | where | 
|  | Self: TryInto<U>, | 
|  | { | 
|  | <Self as TryInto<U>>::try_into(self) | 
|  | .ok() | 
|  | .unwrap_or_else(die) | 
|  | } | 
|  | } | 
|  |  | 
|  | // Deterministically abort on arithmetic overflow, instead of wrapping and | 
|  | // continuing with invalid behavior. | 
|  | // | 
|  | // This is impossible or nearly impossible to hit as the arithmetic computations | 
|  | // in libyaml are all related to either: | 
|  | // | 
|  | //  - small integer processing (ascii, hex digits) | 
|  | //  - allocation sizing | 
|  | // | 
|  | // and the only allocations in libyaml are for fixed-sized objects and | 
|  | // geometrically growing buffers with a growth factor of 2. So in order for an | 
|  | // allocation computation to overflow usize, the previous allocation for that | 
|  | // container must have been filled to a size of usize::MAX/2, which is an | 
|  | // allocation that would have failed in the allocator. But we check for this to | 
|  | // be pedantic and to find out if it ever does happen. | 
|  | // | 
|  | // No-std abort is implemented using a double panic. On most platforms the | 
|  | // current mechanism for this is for core::intrinsics::abort to invoke an | 
|  | // invalid instruction. On Unix, the process will probably terminate with a | 
|  | // signal like SIGABRT, SIGILL, SIGTRAP, SIGSEGV or SIGBUS. The precise | 
|  | // behaviour is not guaranteed and not stable, but is safe. | 
|  | #[cold] | 
|  | pub(crate) fn die<T>() -> T { | 
|  | struct PanicAgain; | 
|  |  | 
|  | impl Drop for PanicAgain { | 
|  | fn drop(&mut self) { | 
|  | panic!("arithmetic overflow"); | 
|  | } | 
|  | } | 
|  |  | 
|  | fn do_die() -> ! { | 
|  | let _panic_again = PanicAgain; | 
|  | panic!("arithmetic overflow"); | 
|  | } | 
|  |  | 
|  | do_die(); | 
|  | } |