golangify 1.4.24

published at 01.04.2024 this crate brings familiar flavor for newcomers from golang
Documentation
//! #golangify
//! golangify macro would turn standard rust Result<T,E> into
//! simple, familiar and convenient tuple (T,E);
//!
//! ## Example  usage 
//! ```rust,no_run
//! use golangify::*;
//! 
//! fn main() {
//!     let (res, err) = golangify!(some_func());
//!     if err != nil {
//!         println!("{:?}", err);
//!     }
//! }
//! 
//! fn some_func() -> Result<u32, &'static str> {
//!     Err("42")
//! }
//! ```
//! 
//! 
//! 01.04.2024

use std::{error::Error, fmt::Display, ops::Deref};

/// Enum Nullable represents variants returned by golangify! macro.
#[derive(Debug)]
#[allow(unused)]
pub enum Nullable<T> {
    Nil,
    Value(T)
}

/// Helper struct for nil constant
pub struct Nil;

/// Constant to match with golang flavor with Nullable::Nil
#[allow(non_upper_case_globals, unused)]
pub const nil: Nil = Nil;

impl<T> PartialEq for Nullable<T> {
    fn eq(&self, other: &Self) -> bool {
        matches!((self, other), (Nullable::Nil, Nullable::Nil))
    }
}

impl<T> PartialEq<Nil> for Nullable<T> {
    fn eq(&self, _: &Nil) -> bool {
        matches!(self, Nullable::Nil)
    }
}

impl<T> PartialEq<Nullable<T>> for Nil {
    fn eq(&self, other: &Nullable<T>) -> bool {
        matches!(other, Nullable::Nil)
    }
}

impl<T> Deref for Nullable<T> {
    type Target = T;

    fn deref(&self) -> &T {
        match self {
            Nullable::Nil => panic!("deref of a null value"),
            Nullable::Value(value) => value,
        }
    }
}

impl<E: Error> Error for Nullable<E> {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            Nullable::Nil => None,
            Nullable::Value(error) => error.source(),
        }
    }
}

impl<T: Display> Display for Nullable<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Nullable::Nil => write!(f, "nil"),
            Nullable::Value(value) => write!(f, "{}", value),
        }
    }
}

/// Macro golangify! do all the magic.
/// 
/// golangify macro would turn standard rust Result<T,E> into
/// simple, familiar and convenient tuple (T,E).
///
/// ### Example  usage 
/// ```rust,no_run
/// use golangify::*;
/// 
/// fn main() {
///     let (res, err) = golangify!(some_func());
///     if err != nil {
///         println!("{:?}", err);
///     }
/// }
/// 
/// fn some_func() -> Result<u32, &'static str> {
///     Err("42")
/// }
/// ```
#[macro_export]
#[allow(unused_macros)]
macro_rules! golangify {
    ($result:expr) => {
        match $result {
            Ok(value) => (Nullable::Value(value), Nullable::Nil),
            Err(error) => (Nullable::Nil, Nullable::Value(error)),
        }
    };
}


#[cfg(test)]
mod tests {
    use super::{golangify, Nullable, nil};

    #[test]
    fn it_works() {

        fn some_func() -> Result<u32, &'static str> {
            Err("42")
        }

        #[allow(unused)]
        let (res, err) = golangify!(some_func());
        if err != nil {
            println!("{:?}", err);
        }
    }

}