feat: imrpovement and add more methods to Option and Result

This commit is contained in:
DL
2024-02-28 15:16:01 +01:00
parent 8a96704909
commit 47a2d0a64d
2 changed files with 513 additions and 54 deletions

321
src/ro.h
View File

@ -4,13 +4,14 @@
#include <stdexcept>
#include <string>
#include <memory>
#include <functional>
#include <functional>
#include <tuple>
#define None(T) (ro::Option<T>())
#define Some(v) (ro::Option(v))
#define ERR(fmt,...) Error(ro::sfmt("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__))
#define Err(e) (ro::Result(e))
#define Ok(v) (ro::Result(v))
#define ERR(fmt, ...) Error(ro::sfmt("%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__))
// #define Err(e) (ro::Result(e))
// #define Ok(v) (ro::Result(v))
namespace ro
{
@ -33,20 +34,21 @@ namespace ro
public:
Error(const std::string &s) : runtime_error(s){};
Error(const char *s) : runtime_error(s){};
Error(): runtime_error(""){};
Error() : runtime_error(""){};
inline friend bool operator==(const Error& l, const Error& r)
inline friend bool operator==(const Error &l, const Error &r)
{
return std::string(l.what()) == std::string(r.what());
}
inline Error operator+(const Error& other)
inline Error operator+(const Error &other)
{
return Error(std::string(this->what()) + "\n" + other.what());
}
};
template <typename T, typename E> class Result;
template <typename T, typename E>
class Result;
template <typename T>
class Option
@ -56,38 +58,94 @@ namespace ro
Option(T obj) : m_some(obj), m_notnull(true){};
Option() : m_notnull(false){};
Option<T>& operator=(const T& value) {insert(value); return *this;};
inline friend bool operator==(const Option<T>& l, const Option<T>& r) {
if(!l.m_notnull && !r.m_notnull)
Option<T> &operator=(const T &value)
{
insert(value);
return *this;
};
inline friend bool operator==(const Option<T> &l, const Option<T> &r)
{
if (!l.m_notnull && !r.m_notnull)
{
return true;
}
if(l.m_notnull && r.m_notnull)
if (l.m_notnull && r.m_notnull)
{
return l.m_some == r.m_some;
}
return false;
};
inline bool is_none(){return !m_notnull;};
inline bool is_some(){return m_notnull;};
inline T& unwrap()
inline friend Option<T> operator|(const Option<T> &l, const Option<T> &r)
{
if(m_notnull)
if (l.is_some())
{
return l;
}
return r;
}
template <typename U>
inline friend Option<U> operator&(const Option<T> &l, const Option<U> &r)
{
if (l.is_some())
{
return r;
}
return Option<U>();
}
inline friend Option<T> operator^(const Option<T> &l, const Option<T> &r)
{
if (l.is_some() != r.is_some())
{
if (l.is_some())
{
return l;
}
return r;
}
return Option<T>();
}
inline bool is_none() const { return !m_notnull; };
inline bool is_some() const { return m_notnull; };
inline const T &unwrap() const
{
if (m_notnull)
{
return m_some;
}
throw Error("Object is None");
}
inline T& get_or_insert(T value)
inline const T &unwrap_or(const T &alt) const
{
if(!m_notnull)
if (m_notnull)
{
return m_some;
}
return alt;
}
inline T unwrap_or_else(const std::function<T()> &fn) const
{
if (m_notnull)
{
return m_some;
}
return fn();
}
inline const T &get_or_insert(const T &value)
{
if (!m_notnull)
{
insert(value);
}
return m_some;
}
inline T& insert(T value)
inline const T &insert(const T &value)
{
m_some = value;
m_notnull = true;
@ -95,35 +153,92 @@ namespace ro
}
template <typename E>
inline Result<T, E> ok_or(E err)
inline Result<T, E> ok_or(const E &err)
{
if(m_notnull)
if (m_notnull)
{
return Result<T, E>(m_some);
}
return Result<T, E>(err);
}
template<typename U>
inline Option<U> map(const std::function<U(T)>& fn)
template <typename U>
inline Option<U> and_then(const std::function<Option<U>(const T &)> &fn)
{
if(is_some())
if (m_notnull)
{
return fn(m_some);
}
return Option<U>();
}
template<typename U>
inline U map_or(U defv, const std::function<U(T)>& fn)
inline Option<T> or_else(const std::function<Option<T>()> &fn)
{
if(is_some())
if (m_notnull)
{
return *this;
}
return fn();
}
template <typename U>
inline Option<U> map(const std::function<U(const T &)> &fn)
{
if (is_some())
{
return fn(m_some);
}
return Option<U>();
}
template <typename U>
inline U map_or(const U &defv, const std::function<U(const T &)> &fn)
{
if (is_some())
{
return fn(m_some);
}
return defv;
}
inline Option<T> filter(const std::function<bool(const T &)> &fn)
{
if (is_some() && fn(m_some))
{
return Option<T>(m_some);
}
return Option<T>();
}
inline Option<T> take()
{
if (m_notnull)
{
m_notnull = false;
return Option<T>(m_some);
}
return Option<T>();
}
inline Option<T> take_if(const std::function<bool(const T &)> &fn)
{
if (m_notnull && fn(m_some))
{
return take();
}
return Option<T>();
}
template <typename U>
inline Option<std::tuple<T, U>> zip(const Option<U> &other)
{
if (m_notnull && other.is_some())
{
return Option<std::tuple<T, U>>(std::tuple<T, U>(m_some, other.unwrap()));
}
return Option<std::tuple<T, U>>();
}
private:
T m_some;
bool m_notnull;
@ -134,66 +249,172 @@ namespace ro
{
public:
Result(T obj) : m_result(obj) {};
Result(T obj) : m_result(obj){};
Result(E err) { m_error.insert(err); };
Result(){};
inline Result<T,E>& operator=(const T& value) {m_result = value; m_error = None(E); return *this;};
inline Result<T,E>& operator=(const E& err) {m_error.insert(err); return *this;};
inline bool is_ok(){return m_error.is_none();};
inline bool is_err(){return m_error.is_some();};
inline T& unwrap()
inline Result<T, E> &operator=(const T &value)
{
if(is_ok())
m_result = value;
m_error = None(E);
return *this;
};
inline Result<T, E> &operator=(const E &err)
{
m_error.insert(err);
return *this;
};
inline friend bool operator==(const Result<T, E> &l, const Result<T, E> &r)
{
if (l.is_ok() != r.is_ok())
{
return false;
}
if (l.is_ok())
{
return l.m_result == r.m_result;
}
return l.m_error == r.m_error;
};
inline friend bool operator==(const Result<T, E> &l, const E &r)
{
if (l.is_ok())
{
return false;
}
return l.m_error == r;
};
inline friend bool operator==(const Result<T, E> &l, const T &r)
{
if (l.is_err())
{
return false;
}
return l.m_result == r;
};
inline friend Result<T, E> operator|(const Result<T, E> &l, const Result<T, E> &r)
{
if (l.is_ok())
{
return l;
}
return r;
}
template <typename U>
inline friend Result<U, E> operator&(const Result<T, E> &l, const Result<U, E> &r)
{
if (l.is_ok())
{
return r;
}
return Result<U, E>(l.m_error.unwrap());
}
inline bool is_ok() const { return m_error.is_none(); };
inline bool is_err() const { return m_error.is_some(); };
template <typename F>
inline Result<T, F> or_else(const std::function<Result<T, F>(const E &)> &fn)
{
if (is_ok())
{
return Result<T, F>(m_result);
}
return fn(m_error.unwrap());
}
inline const T &unwrap() const
{
if (is_ok())
{
return m_result;
}
throw m_error.unwrap();
}
inline T& expect(E e)
inline const E &unwrap_err() const
{
if(is_ok())
if (is_err())
{
return m_error.unwrap();
}
throw m_result;
}
inline const T &expect(E e) const
{
if (is_ok())
{
return m_result;
}
throw e + m_error.unwrap();
}
template<typename U>
inline Result<U,E> map(const std::function<U(T)>& fn)
template <typename U>
inline Result<U, E> map(const std::function<U(const T &)> &fn)
{
if(is_ok())
if (is_ok())
{
return fn(m_result);
}
return m_error.unwrap();
}
template<typename E1>
inline Result<T,E1> map_err(const std::function<E1(E)>& fn)
template <typename E1>
inline Result<T, E1> map_err(const std::function<E1(const E &)> &fn)
{
if(!is_ok())
if (!is_ok())
{
return fn(m_error.unwrap());
}
return m_result;
}
template<typename U>
inline U map_or(U defv, const std::function<U(T)>& fn)
template <typename U>
inline U map_or(const U &defv, const std::function<U(const T &)> &fn)
{
if(is_ok())
if (is_ok())
{
return fn(m_result);
}
return defv;
}
Option<E> err() { return m_error; }
Option<T> ok() { return is_ok()?Option<T>(m_result): Option<T>(); }
template <typename U>
inline Result<U, E> and_then(const std::function<Result<U, E>(const T &)> &fn)
{
if (is_ok())
{
return fn(m_result);
}
return Result<U, E>(m_error.unwrap());
}
inline const T &unwrap_or(const T &alt) const
{
if (is_ok())
{
return m_result;
}
return alt;
}
inline T unwrap_or_else(const std::function<T(const E &)> &fn)
{
if (is_ok())
{
return m_result;
}
return fn(m_error.unwrap());
}
inline const Option<E> &err() const { return m_error; }
inline Option<T> ok() const { return is_ok() ? Option<T>(m_result) : Option<T>(); }
private:
T m_result;