Skip to content

Commit

Permalink
Core Lib Documentation: Zeroable module (#6722)
Browse files Browse the repository at this point in the history
Co-authored-by: enitrat <[email protected]>
  • Loading branch information
TAdev0 and enitrat authored Nov 29, 2024
1 parent 3b10438 commit 2dc18c2
Showing 1 changed file with 16 additions and 26 deletions.
42 changes: 16 additions & 26 deletions corelib/src/zeroable.cairo
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
// === Zeroable ===
//! Types and traits for handling non-zero values and zero checking operations.
//!
//! This module provides the [`NonZero`] wrapper type which guarantees that a value is never
//! zero.
//! The [`Zeroable`] trait is meant for internal use only. The public-facing equivalent is the
//! [`Zero`] trait.
//!
//! [`Zero`]: core::num::traits::zero::Zero

/// A trait for types that have a concept of zero and can be compared to zero.
///
/// This trait is useful for numeric types or any type that has an additive identity element.
pub(crate) trait Zeroable<T> {
/// Returns the additive identity element of Self, 0.
/// Returns the additive identity element of `self`, 0.
///
/// This method should return a value that, when added to any other value of type T,
/// This method should return a value that, when added to any other value of type `T`,
/// does not change that value.
///
/// # Examples
///
/// ```
/// assert_eq!(Zeroable::<i32>::zero(), 0);
/// assert!(Zeroable::<i32>::zero() == 0);
/// ```
#[must_use]
fn zero() -> T;

/// Returns whether self is equal to 0, the additive identity element.
/// Returns whether `self` is equal to 0, the additive identity element.
///
/// # Examples
///
Expand All @@ -28,7 +35,7 @@ pub(crate) trait Zeroable<T> {
#[must_use]
fn is_zero(self: T) -> bool;

/// Returns whether self is not equal to 0, the additive identity element.
/// Returns whether `self` is not equal to 0, the additive identity element.
///
/// This method is the logical inverse of `is_zero()`.
///
Expand All @@ -48,18 +55,15 @@ pub(crate) mod zero_based {
pub(crate) impl ZeroableImpl<
T, impl ZeroImpl: crate::num::traits::Zero<T>, +Drop<T>, +Copy<T>,
> of super::Zeroable<T> {
/// Returns the zero value for the type.
fn zero() -> T {
ZeroImpl::zero()
}

/// Checks if the value is zero.
#[inline]
fn is_zero(self: T) -> bool {
ZeroImpl::is_zero(@self)
}

/// Checks if the value is non-zero.
#[inline]
fn is_non_zero(self: T) -> bool {
ZeroImpl::is_non_zero(@self)
Expand All @@ -69,13 +73,13 @@ pub(crate) mod zero_based {

pub(crate) impl Felt252Zeroable = zero_based::ZeroableImpl<felt252>;

// === NonZero ===

/// A wrapper type for non-zero values of type T.
///
/// This type guarantees that the wrapped value is never zero.
#[derive(Copy, Drop)]
pub extern type NonZero<T>;

impl NonZeroNeg<T, +Neg<T>, +TryInto<T, NonZero<T>>> of Neg<NonZero<T>> {
fn neg(a: NonZero<T>) -> NonZero<T> {
// TODO(orizi): Optimize using bounded integers.
Expand All @@ -89,26 +93,20 @@ impl NonZeroNeg<T, +Neg<T>, +TryInto<T, NonZero<T>>> of Neg<NonZero<T>> {
pub(crate) enum IsZeroResult<T> {
/// Indicates that the value is zero.
Zero,
/// Indicates that the value is non-zero, wrapping it in a NonZero<T>.
/// Indicates that the value is non-zero, wrapping it in a `NonZero<T>`.
NonZero: NonZero<T>,
}

/// Unwraps a NonZero<T> to retrieve the underlying value of type T.
/// Unwraps a `NonZero<T>` to retrieve the underlying value of type `T`.
extern fn unwrap_non_zero<T>(a: NonZero<T>) -> T nopanic;

/// Implements the `Into` trait for converting NonZero<T> to T.
pub(crate) impl NonZeroIntoImpl<T> of Into<NonZero<T>, T> {
/// Converts a NonZero<T> to T.
fn into(self: NonZero<T>) -> T nopanic {
unwrap_non_zero(self)
}
}

/// Implements the `Into` trait for converting IsZeroResult<T> to bool.
impl IsZeroResultIntoBool<T, +Drop<T>> of Into<IsZeroResult<T>, bool> {
/// Converts an IsZeroResult<T> to a boolean.
///
/// Returns true if the result is Zero, false otherwise.
fn into(self: IsZeroResult<T>) -> bool {
match self {
IsZeroResult::Zero => true,
Expand All @@ -117,17 +115,14 @@ impl IsZeroResultIntoBool<T, +Drop<T>> of Into<IsZeroResult<T>, bool> {
}
}

/// Implements the `PartialEq` trait for NonZero<T>.
impl NonZeroPartialEq<T, +PartialEq<T>, +Copy<T>, +Drop<T>> of PartialEq<NonZero<T>> {
/// Checks if two NonZero<T> values are equal.
#[inline]
fn eq(lhs: @NonZero<T>, rhs: @NonZero<T>) -> bool {
let lhs: T = (*lhs).into();
let rhs: T = (*rhs).into();
lhs == rhs
}

/// Checks if two NonZero<T> values are not equal.
#[inline]
fn ne(lhs: @NonZero<T>, rhs: @NonZero<T>) -> bool {
let lhs: T = (*lhs).into();
Expand All @@ -136,17 +131,12 @@ impl NonZeroPartialEq<T, +PartialEq<T>, +Copy<T>, +Drop<T>> of PartialEq<NonZero
}
}

/// Implements the `Serde` trait for NonZero<T>.
impl NonZeroSerde<T, +Serde<T>, +Copy<T>, +Drop<T>, +TryInto<T, NonZero<T>>> of Serde<NonZero<T>> {
/// Serializes a NonZero<T> value.
fn serialize(self: @NonZero<T>, ref output: Array<felt252>) {
let value: T = (*self).into();
value.serialize(ref output);
}

/// Deserializes a NonZero<T> value.
///
/// Returns None if deserialization fails or if the deserialized value is zero.
fn deserialize(ref serialized: Span<felt252>) -> Option<NonZero<T>> {
Serde::<T>::deserialize(ref serialized)?.try_into()
}
Expand Down

0 comments on commit 2dc18c2

Please sign in to comment.