use std::{error::Error, fmt::Display, ops::Deref};
#[derive(Debug)]
#[allow(unused)]
pub enum Nullable<T> {
Nil,
Value(T)
}
pub struct 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_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);
}
}
}