provekit_noirc_driver 1.0.0-beta.20-alpha.1

Noir compiler driver.
Documentation
use crate::cmp::{Eq, Ord, Ordering};
use crate::default::Default;
use crate::hash::{Hash, Hasher};

/// Represents a value of type T or its absence.
/// Use `Option::some(value)` to construct a value or `Option::none()` to record the absence of one.
pub struct Option<T> {
    _is_some: bool,
    _value: T,
}

impl<T> Option<T> {
    /// Constructs a None value
    pub fn none() -> Self {
        Self { _is_some: false, _value: crate::mem::zeroed() }
    }

    /// Constructs a Some wrapper around the given value
    pub fn some(_value: T) -> Self {
        Self { _is_some: true, _value }
    }

    /// True if this Option is None
    pub fn is_none(&self) -> bool {
        !self._is_some
    }

    /// True if this Option is Some
    pub fn is_some(&self) -> bool {
        self._is_some
    }

    /// Asserts `self.is_some()` and returns the wrapped value.
    pub fn unwrap(self) -> T {
        assert(self._is_some);
        self._value
    }

    /// Returns the inner value without asserting `self.is_some()`
    /// Note that if `self` is `None`, there is no guarantee what value will be returned,
    /// only that it will be of type `T`.
    pub fn unwrap_unchecked(self) -> T {
        self._value
    }

    /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.
    pub fn unwrap_or(self, default: T) -> T {
        if self._is_some {
            self._value
        } else {
            default
        }
    }

    /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return
    /// a default value.
    pub fn unwrap_or_else<Env>(self, default: fn[Env]() -> T) -> T {
        if self._is_some {
            self._value
        } else {
            default()
        }
    }

    /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value
    pub fn expect<let N: u32, MessageTypes>(self, message: fmtstr<N, MessageTypes>) -> T {
        assert(self.is_some(), message);
        self._value
    }

    /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.
    pub fn map<U, Env>(self, f: fn[Env](T) -> U) -> Option<U> {
        if self._is_some {
            Option::some(f(self._value))
        } else {
            Option::none()
        }
    }

    /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.
    pub fn map_or<U, Env>(self, default: U, f: fn[Env](T) -> U) -> U {
        if self._is_some {
            f(self._value)
        } else {
            default
        }
    }

    /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.
    pub fn map_or_else<U, Env1, Env2>(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {
        if self._is_some {
            f(self._value)
        } else {
            default()
        }
    }

    /// Returns None if self is None. Otherwise, this returns `other`.
    pub fn and(self, other: Self) -> Self {
        if self.is_none() {
            Option::none()
        } else {
            other
        }
    }

    /// If self is None, this returns None. Otherwise, this calls the given function
    /// with the Some value contained within self, and returns the result of that call.
    ///
    /// In some languages this function is called `flat_map` or `bind`.
    pub fn and_then<U, Env>(self, f: fn[Env](T) -> Option<U>) -> Option<U> {
        if self._is_some {
            f(self._value)
        } else {
            Option::none()
        }
    }

    /// If self is Some, return self. Otherwise, return `other`.
    pub fn or(self, other: Self) -> Self {
        if self._is_some {
            self
        } else {
            other
        }
    }

    /// If self is Some, return self. Otherwise, return `default()`.
    pub fn or_else<Env>(self, default: fn[Env]() -> Self) -> Self {
        if self._is_some {
            self
        } else {
            default()
        }
    }

    // If only one of the two Options is Some, return that option.
    // Otherwise, if both options are Some or both are None, None is returned.
    pub fn xor(self, other: Self) -> Self {
        if self._is_some {
            if other._is_some {
                Option::none()
            } else {
                self
            }
        } else if other._is_some {
            other
        } else {
            Option::none()
        }
    }

    /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.
    /// Otherwise, this returns `None`
    pub fn filter<Env>(self, predicate: fn[Env](T) -> bool) -> Self {
        if self._is_some {
            if predicate(self._value) {
                self
            } else {
                Option::none()
            }
        } else {
            Option::none()
        }
    }

    /// Flattens an Option<Option<T>> into a Option<T>.
    /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.
    pub fn flatten(option: Option<Option<T>>) -> Option<T> {
        if option._is_some {
            option._value
        } else {
            Option::none()
        }
    }
}

impl<T> Default for Option<T> {
    fn default() -> Self {
        Option::none()
    }
}

impl<T> Eq for Option<T>
where
    T: Eq,
{
    fn eq(self, other: Self) -> bool {
        if self._is_some == other._is_some {
            if self._is_some {
                self._value == other._value
            } else {
                true
            }
        } else {
            false
        }
    }
}

impl<T> Hash for Option<T>
where
    T: Hash,
{
    fn hash<H>(self, state: &mut H)
    where
        H: Hasher,
    {
        self._is_some.hash(state);
        if self._is_some {
            self._value.hash(state);
        }
    }
}

// For this impl we're declaring Option::none < Option::some
impl<T> Ord for Option<T>
where
    T: Ord,
{
    fn cmp(self, other: Self) -> Ordering {
        if self._is_some {
            if other._is_some {
                self._value.cmp(other._value)
            } else {
                Ordering::greater()
            }
        } else if other._is_some {
            Ordering::less()
        } else {
            Ordering::equal()
        }
    }
}