Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // main.cpp
- // rustic
- //
- // Created by Antony Searle on 21/7/18.
- // Copyright © 2018 Antony Searle. All rights reserved.
- //
- #include <utility>
- #include <iostream>
- #include <cassert>
- #include <mutex>
- namespace rust {
- void panic() {
- std::terminate();
- }
- void panic(const char* msg) {
- std::cerr << msg << std::endl;
- std::terminate();
- }
- template<typename T>
- struct Cell {
- Cell(T&& value)
- : _value(std::move(value)) {
- }
- T get() const& {
- return std::as_const(this->_value);
- }
- void set(T&& value) const& {
- _value = std::move(value);
- }
- T& get_mut() & {
- return this->_value;
- }
- void swap(Cell<T> const& other) const& {
- std::swap(_value, other._value);
- }
- T replace(T&& value) const& {
- return std::exchange(_value, std::move(value));
- }
- T into_inner() && {
- return std::move(_value);
- }
- T take() const& {
- return std::exchange(_value, T());
- }
- static Cell from(T&& value) {
- return Cell(std::move(value));
- }
- Cell clone() const& {
- return Cell(get());
- }
- Cell() : _value() {}
- private:
- mutable T _value;
- };
- template<typename T>
- std::ostream& operator<<(std::ostream& a, Cell<T> const& b) {
- return a << "Cell(" << b.get() << std::endl;
- }
- template<typename T>
- struct Option {
- private:
- std::aligned_storage_t<sizeof(T), alignof(T)> _value;
- bool _is_some;
- bool is_some() const& { return _is_some; }
- bool is_none() const& { return !_is_some; }
- Option<T const&> as_ref() const&;
- Option<T &> as_mut() &;
- T expect(const char* msg) && {
- if (!_is_some)
- panic();
- return reinterpret_cast<T&&>(_value);
- }
- T unwrap(const char* msg) && {
- if (!_is_some)
- panic();
- return reinterpret_cast<T&&>(_value);
- }
- T unwrap_or(T&& def) && {
- if (!_is_some)
- return std::move(def);
- return reinterpret_cast<T&&>(_value);
- }
- template<typename F>
- T unwrap_or_else(F&& f) && {
- if (_is_some)
- return std::forward<F>(f)();
- return reinterpret_cast<T&&>(_value);
- }
- template<typename U, typename F>
- Option<U> map(F&& f) &&;
- template<typename U, typename F>
- U map(U&& def, F&& f) &&;
- };
- template<typename T, typename E>
- struct Result {
- private:
- union {
- T _ok;
- E _err;
- };
- bool _is_err;
- public:
- bool is_ok() const& { return !_is_err; }
- bool is_err() const& { return _is_err; }
- };
- template<typename T>
- struct Ref;
- template<typename T>
- struct RefMut;
- struct BorrowError {};
- struct BorrowMutError {};
- template<typename T>
- struct RefCell {
- RefCell()
- : _value()
- , _borrowers(0) {
- }
- explicit RefCell(T&& value)
- : _value(std::move(value))
- , _borrowers(0) {
- }
- ~RefCell() {
- assert(!_borrowers);
- }
- T into_inner() && {
- assert(!_borrowers);
- return std::move(this->_value);
- }
- T replace(T&& value) const& {
- if (_borrowers)
- panic();
- return std::exchange(this->_value, std::move(value));
- }
- void swap(RefCell<T> const& other) const& {
- if (_borrowers || other._borrowers)
- panic();
- std::swap(this->_value, other->_value);
- }
- Ref<T> borrow() const&;
- Result<Ref<T>, BorrowError> try_borrow() const&;
- RefMut<T> borrow_mut() const&;
- Result<RefMut<T>, BorrowMutError> try_borrow_mut() const&;
- T* as_ptr() const& { return &_value; }
- T& get_mut() & { return _value; }
- private:
- mutable T _value;
- mutable std::ptrdiff_t _borrowers;
- friend class Ref<T>;
- friend class RefMut<T>;
- };
- template<typename T>
- std::ostream& operator<<(std::ostream& a, RefCell<T> const& b) {
- return a << "RefCell { value: " << *b.borrow() << "}";
- }
- template<typename T>
- struct Ref {
- static Ref clone(Ref const& orig) {
- return Ref(orig);
- }
- Ref() = delete;
- Ref(Ref const& other) : _cell(other._cell) {
- assert(_cell);
- ++_cell->_borrowers;
- }
- Ref(Ref&& other) : _cell(std::exchange(other._cell, nullptr)) {}
- ~Ref() {
- if (_cell) {
- assert(_cell->_borrowers > 0);
- --_cell->_borrowers;
- }
- }
- T const& operator*() const& {
- assert(_cell);
- return _cell->_value;
- }
- operator T const&() const& {
- assert(_cell);
- return _cell->_value;
- }
- T const* operator->() const& {
- assert(_cell);
- return &_cell->_value;
- }
- private:
- friend class RefCell<T>;
- explicit Ref(RefCell<T> const* cell)
- : _cell(cell) {
- assert(cell);
- }
- RefCell<T> const* _cell;
- };
- template<typename T>
- std::ostream& operator<<(std::ostream& a, Ref<T> const& b) {
- return a << *b;
- }
- template<typename T>
- struct RefMut {
- RefMut() = delete;
- RefMut(RefMut const& other) = delete;
- RefMut(RefMut && other)
- : _cell(std::exchange(other._cell, nullptr)) {
- assert(_cell);
- }
- ~RefMut() {
- if (_cell) {
- assert(_cell->_borrowers == -1);
- _cell->_borrowers = 0;
- }
- }
- T const& operator*() const& {
- assert(_cell);
- return _cell->_value;
- }
- T const* operator->() const& {
- assert(_cell);
- return &_cell->_value;
- }
- operator T const&() const& {
- assert(_cell);
- return _cell->_value;
- }
- operator T&() & {
- assert(_cell);
- return _cell->_value;
- }
- T& operator*() & {
- assert(_cell);
- return _cell->_value;
- }
- T* operator->() & {
- assert(_cell);
- return _cell->_value;
- }
- private:
- explicit RefMut(RefCell<T> const* cell)
- : _cell(cell) {
- assert(cell);
- }
- RefCell<T> const* _cell;
- friend class RefCell<T>;
- };
- template<typename T>
- std::ostream& operator<<(std::ostream& a, RefMut<T> const& b) {
- return a << *b;
- }
- template<typename T>
- Ref<T> RefCell<T>::borrow() const& {
- if (_borrowers == -1) {
- panic("Can't borrow RefCell because it is already mutably borrowed");
- }
- ++_borrowers;
- return Ref<T>(this);
- }
- template<typename T>
- RefMut<T> RefCell<T>::borrow_mut() const& {
- if (_borrowers != 0) {
- panic("Can't mutably borrow RefCell because it is already borrowed");
- }
- --_borrowers;
- return RefMut<T>(this);
- }
- template<typename T>
- void drop(T& value) {
- T _value(std::move(value));
- }
- template<typename T>
- struct Box {
- Box() : _ptr(new T()) {}
- Box(Box const&) = delete;
- Box(Box&& other)
- : _ptr(std::exchange(other._ptr, nullptr)) {
- }
- ~Box() {
- delete _ptr;
- }
- Box& operator=(Box const&) = delete;
- Box& operator=(Box&& other) {
- _ptr = std::exchange(other._ptr, nullptr);
- return *this;
- }
- explicit Box(T&& x)
- : _ptr(new T(std::move(x))) {
- }
- static Box from_raw(T* raw) {
- assert(raw);
- return Box(raw);
- }
- static T* into_raw(Box<T>&& b) {
- assert(b._ptr);
- return std::exchange(b._ptr, nullptr);
- }
- static T& leak(Box<T>&& b) {
- assert(b._ptr);
- return *std::exchange(b._ptr, nullptr);
- }
- const T& operator*() const & {
- assert(_ptr);
- return *_ptr;
- }
- operator const T& () const& {
- assert(_ptr);
- return *_ptr;
- }
- T& operator*() & {
- assert(_ptr);
- return *_ptr;
- }
- operator T& () & {
- assert(_ptr);
- return *_ptr;
- }
- T const* operator->() const& {
- assert(_ptr);
- return _ptr;
- }
- T* operator->() & {
- assert(_ptr);
- return _ptr;
- }
- private:
- explicit Box(T* raw)
- : _ptr(raw) {
- }
- T* _ptr;
- }; // Box
- template<typename T>
- std::ostream& operator<<(std::ostream& a, Box<T> const& b) {
- return a << *b;
- }
- template<typename T>
- struct Rc {
- private:
- struct holder {
- T _value;
- std::ptrdiff_t _count;
- holder()
- : _value()
- , _count(0) {
- }
- holder(T&& value)
- : _value(std::move(value))
- , _count(0) {}
- };
- holder _ptr;
- explicit Rc(holder* p) : _ptr(p) {}
- public:
- Rc() : _ptr(new holder()) {}
- Rc(Rc const&) = delete;
- Rc(Rc&& other) : _ptr(other._ptr) { assert(_ptr); ++_ptr->_count; }
- ~Rc() { delete _ptr; }
- static Result<T, Rc<T>> try_unwrap(Rc&&);
- static T const* into_raw(Rc&& r) {
- return &r._ptr._value;
- }
- static Rc from_raw(T const* p) {
- return Rc(reinterpret_cast<holder const*>(p));
- }
- size_t strong_count() const& { assert(_ptr); return _ptr->_count + 1; }
- static Option<T&> get_mut(Rc<T>&);
- static T& make_mut(Rc<T>& r) {
- assert(r._ptr);
- if (r._ptr->_count) {
- --r._ptr->_count;
- r._ptr = new holder(T(r._ptr._value));
- }
- return r._ptr->_value;
- }
- T const& operator*() const& { assert(_ptr); return _ptr->_value; }
- operator T const&() const& { assert(_ptr); return _ptr->_value; }
- T const* operator->() const& { assert(_ptr); return &_ptr->_value; }
- };
- using usize = size_t;
- template<typename T>
- struct Slice {
- private:
- T* _begin;
- usize _len;
- public:
- usize len() const& { return _len; }
- bool is_empty() const& { return _len != 0; }
- };
- template<typename T>
- struct Vec {
- private:
- std::vector<T> _vector;
- Vec(const Vec&) = default;
- Vec& operator=(const Vec&) = default;
- public:
- Vec() = default;
- Vec(Vec&& other) = default;
- ~Vec() = default;
- Vec& operator=(Vec&& other) = default;
- static Vec with_capacity(usize capacity) { Vec v; v._vector.reserve(capacity); return v; }
- usize capacity() const& { return _vector.capacity(); }
- void reserve(usize additional) & { _vector.reserve(_vector.size() + additional); }
- void shrink_to_fit() & { _vector.shrink_to_fit(); }
- void truncate(usize len) & { if (len < _vector.size()) _vector.resize(len); }
- T swap_remove(usize index) & {
- if (index >= _vector.size())
- panic("Out of bounds");
- T result(std::move(_vector[index]));
- _vector[index] = std::move(_vector.back());
- _vector.pop_back();
- return result;
- }
- void insert(usize index, T&& element) & {
- _vector.insert(_vector.cbegin() + index, std::move(element));
- }
- T remove(usize index) & {
- auto p = _vector.begin() + index;
- T v(std::move(*p));
- _vector.erase(p);
- return v;
- }
- void push(T&& value) & {
- _vector.push_back(std::move(value));
- }
- Option<T> pop() &;
- void append(Vec<T>& other) & {
- reserve(other._vector.size());
- std::move(other.begin(), other.end(), std::back_inserter(_vector));
- other._vector.clear();
- }
- void clear() & { _vector.clear(); }
- usize len() const& { return _vector.size(); }
- bool is_empty() const& { return _vector.empty(); }
- Vec split_off(usize at) & {
- if (at > _vector.size())
- panic();
- Vec v = Vec::with_capacity(_vector.size() - at);
- std::move(_vector.begin() + at, _vector.end(), std::back_inserter(v._vector));
- _vector.resize(at);
- return v;
- }
- void dedup() & {
- _vector.erase(std::unique(_vector.begin(), _vector.end()), _vector.end());
- }
- Option<T const&> first() const&;
- Option<T&> first_mut() &;
- Option<T const&> last() const&;
- Option<T&> last_mut() &;
- void reverse() & { std::reverse(_vector.begin(), _vector.end()); }
- Vec clone() const& {
- return Vec(*this);
- }
- T& operator[](usize index) & {
- if (index >= _vector.size())
- panic();
- return _vector[index];
- }
- T const& operator[](usize index) const& {
- if (index >= _vector.size())
- panic();
- return _vector[index];
- }
- }; // struct Vec<T>
- template<typename T>
- struct Mutex;
- template<typename T>
- struct MutexGuard {
- private:
- Mutex<T> const* _ptr;
- explicit MutexGuard(Mutex<T> const& p)
- : _ptr(&p) {
- assert(_ptr);
- _ptr->_mutex.lock();
- }
- friend class Mutex<T>;
- public:
- MutexGuard(MutexGuard const&) = delete;
- MutexGuard(MutexGuard&& other)
- : _ptr(std::exchange(other._ptr, nullptr)) {
- }
- ~MutexGuard() {
- if (_ptr)
- _ptr->_mutex.unlock();
- }
- MutexGuard& operator=(MutexGuard const& other) {
- assert(_ptr);
- assert(other._ptr);
- _ptr->_value = other._ptr->_value;
- return *this;
- }
- operator T const&() const& {
- assert(_ptr);
- return _ptr->_value;
- }
- T const& operator*() const& {
- assert(_ptr);
- return _ptr->_value;
- }
- T const* operator->() const& {
- assert(_ptr);
- return &_ptr->_value;
- }
- operator T&() & {
- assert(_ptr);
- return _ptr->_value;
- }
- T& operator*() & {
- assert(_ptr);
- return _ptr->_value;
- }
- T* operator->() & {
- assert(_ptr);
- return &_ptr->_value;
- }
- };
- template<typename T>
- struct Mutex {
- private:
- friend class MutexGuard<T>;
- mutable T _value;
- mutable std::mutex _mutex;
- public:
- Mutex() = default;
- Mutex(Mutex const&) = delete;
- Mutex& operator=(Mutex const&) = delete;
- explicit Mutex(T&& value) : _value(std::move(value)) {}
- MutexGuard<T> lock() const& {
- return MutexGuard<T>(this);
- }
- T into_inner() && {
- return std::move(_value);
- }
- // No locking occurs because we already have mutable therefore exclusive
- // access
- T& get_mut() & {
- return _value;
- }
- }; // Mutex<T>
- void main() {
- {
- auto a = RefCell(7);
- {
- auto b = a.borrow();
- std::cout << b << std::endl;
- std::cout << a << std::endl;
- // auto c = a.borrow_mut();
- auto d = a.borrow();
- std::cout << d << std::endl;
- // auto e = RefCell<int>(d);
- std::cout << (d + 1) << std::endl;
- }
- {
- auto c = a.borrow_mut();
- c += 2;
- std::cout << c << std::endl;
- // std::cout << a << std::endl;
- }
- }
- {
- auto a = Box(99);
- std::cout << a << std::endl;
- drop(a);
- // std::cout << a << std::endl;
- }
- }
- }
- int main(int argc, const char * argv[]) {
- rust::main();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement