From c72f7f1e9693218c0ba1368a24dbf52e46a6dbfb Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 20 Feb 2018 18:09:39 -0800 Subject: [PATCH] ircd::m: Begin an event::errors fundamental conformity report. --- include/ircd/m/event.h | 38 ++++++++++++ ircd/m/event.cc | 133 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) diff --git a/include/ircd/m/event.h b/include/ircd/m/event.h index 191c1bcf5..16f1db006 100644 --- a/include/ircd/m/event.h +++ b/include/ircd/m/event.h @@ -64,6 +64,7 @@ struct ircd::m::event { struct prev; struct fetch; + struct errors; // Common convenience aliases using id = m::id::event; @@ -128,3 +129,40 @@ struct ircd::m::event::fetch friend bool seek(fetch &, const event::id &, std::nothrow_t); friend void seek(fetch &, const event::id &); }; + +struct ircd::m::event::errors +{ + enum code :uint; + + uint64_t report {0}; + + bool clean() const; + operator bool() const; + bool operator!() const; + bool has(const uint &code) const; + bool has(const code &code) const; + string_view string(const mutable_buffer &out) const; + + void set(const code &code); + void del(const code &code); + + errors() = default; + errors(const event &); + + friend string_view reflect(const code &); + friend std::ostream &operator<<(std::ostream &, const errors &); +}; + +enum ircd::m::event::errors::code +:uint +{ + INVALID_EVENT_ID, + INVALID_ROOM_ID, + INVALID_SENDER_ID, + INVALID_REDACTS_ID, + INVALID_TYPE, + DEPTH_NEGATIVE, + DEPTH_ZERO_NON_CREATE, + + _NUM_ +}; diff --git a/ircd/m/event.cc b/ircd/m/event.cc index 84f26d47a..f3d8a96ff 100644 --- a/ircd/m/event.cc +++ b/ircd/m/event.cc @@ -501,3 +501,136 @@ const { return row.valid(event_id); } + +// +// event::errors +// + +namespace ircd::m +{ + const size_t event_errors_num{num_of()}; + extern const std::array event_errors_reflects; +} + +decltype(ircd::m::event_errors_reflects) +ircd::m::event_errors_reflects +{ + "INVALID_EVENT_ID", + "INVALID_ROOM_ID", + "INVALID_SENDER_ID", + "INVALID_REDACTS_ID", + "DEPTH_NEGATIVE", + "DEPTH_ZERO_NON_CREATE", +}; + +std::ostream & +ircd::m::operator<<(std::ostream &s, const event::errors &errors) +{ + thread_local char buf[1024]; + s << errors.string(buf); + return s; +} + +ircd::string_view +ircd::m::reflect(const event::errors::code &code) +try +{ + return event_errors_reflects.at(code); +} +catch(const std::out_of_range &e) +{ + return "??????"_sv; +} + +ircd::m::event::errors::errors(const event &e) +:report{0} +{ + if(!valid(m::id::EVENT, json::get<"event_id"_>(e))) + set(INVALID_EVENT_ID); + + if(!valid(m::id::ROOM, json::get<"room_id"_>(e))) + set(INVALID_ROOM_ID); + + if(!valid(m::id::USER, json::get<"sender"_>(e))) + set(INVALID_SENDER_ID); + + if(json::get<"type"_>(e) == "m.room.redaction") + if(!valid(m::id::EVENT, json::get<"redacts"_>(e))) + set(INVALID_REDACTS_ID); + + //TODO: XXX + if(empty(json::get<"type"_>(e))) + set(INVALID_TYPE); + + if(json::get<"depth"_>(e) < 0) + set(DEPTH_NEGATIVE); + + if(json::get<"type"_>(e) != "m.room.create") + if(json::get<"depth"_>(e) == 0) + set(DEPTH_ZERO_NON_CREATE); +} + +void +ircd::m::event::errors::del(const code &code) +{ + report &= ~(1UL << code); +} + +void +ircd::m::event::errors::set(const code &code) +{ + report |= (1UL << code); +} + +ircd::string_view +ircd::m::event::errors::string(const mutable_buffer &out) +const +{ + mutable_buffer buf{out}; + for(uint64_t i(0); i < num_of(); ++i) + { + if(!has(code(i))) + continue; + + if(begin(buf) != begin(out)) + consume(buf, copy(buf, " "_sv)); + + consume(buf, copy(buf, reflect(code(i)))); + } + + return { data(out), begin(buf) }; +} + +bool +ircd::m::event::errors::has(const code &code) +const +{ + return report & (1UL << code); +} + +bool +ircd::m::event::errors::has(const uint &code) +const +{ + return (report & (1UL << code)) == code; +} + +bool +ircd::m::event::errors::operator!() +const +{ + return clean(); +} + +ircd::m::event::errors::operator bool() +const +{ + return !clean(); +} + +bool +ircd::m::event::errors::clean() +const +{ + return report == 0; +}