16#ifndef MIRAI_MESSAGECHAIN_HPP_
17#define MIRAI_MESSAGECHAIN_HPP_
68 template<
typename T,
size_t... I>
69 struct is_message_type_<T,
std::index_sequence<I...>> :
public std::disjunction<std::is_same<T, GetType_t<MessageTypesList[I]>>...>
77 template<
typename MessageType>
constexpr static void type_check_()
79 static_assert(std::is_base_of_v<IMessage, MessageType>,
80 "MessageType is not derived from IMessage");
82 "Unsupported messsage type");
94 std::unique_ptr<IMessage> msg_;
98 std::size_t... I,
typename F,
100 std::enable_if_t<(
sizeof...(I) > 0), std::invoke_result_t<F, GetType_t<MessageTypesList[0]>&>> >
101 auto visit_(std::index_sequence<I...>, F&& f) -> std::enable_if_t<
102 std::conjunction_v<std::is_same<Ret, std::invoke_result_t<F, GetType_t<MessageTypesList[I]>&>>...>, Ret >
105 static constexpr std::array<FP,
sizeof...(I)> func = {
109 throw std::runtime_error(
"Cannot call visit() on an empty MessageElement");
110 return func[
static_cast<size_t>(this->type_)](std::forward<F>(f),
this);
113 template< std::size_t... I,
typename F,
114 typename Ret = std::enable_if_t<(
sizeof...(I) > 0),
115 std::invoke_result_t<F, const GetType_t<MessageTypesList[0]>&>> >
116 auto cvisit_(std::index_sequence<I...>, F&& f)
const -> std::enable_if_t<
117 std::conjunction_v<std::is_same<Ret, std::invoke_result_t<F, const GetType_t<MessageTypesList[I]>&>>...>,
121 static constexpr std::array<FP,
sizeof...(I)> func = {[](F&& f,
const MessageElement* p) {
126 throw std::runtime_error(
"Cannot call visit() on an empty MessageElement");
127 return func[
static_cast<size_t>(this->type_)](std::forward<F>(f),
this);
148 if (msg_) this->type_ = this->msg_->type();
153 this->msg_ = std::move(msg);
155 this->type_ = this->msg_->type();
161 if (rhs.msg_) this->msg_ = rhs.msg_->clone();
168 this->type_ = rhs.type_;
169 if (rhs.msg_) this->msg_ = rhs.msg_->clone();
179 explicit operator
bool()
const {
return (
bool)this->msg_; }
181 template<
typename MessageType,
typename... Args,
typename Type = std::decay_t<MessageType>,
182 typename std::enable_if_t<traits::is_message_type<Type>::value,
int> = 0>
184 : msg_(
std::make_unique<Type>(
std::forward<Args>(args)...)), type_(Type::
GetType())
188 template<
typename MessageType,
typename Type = std::decay_t<MessageType>,
189 typename std::enable_if_t<traits::is_message_type<Type>::value,
int> = 0>
191 : msg_(
std::make_unique<Type>(
std::forward<MessageType>(m))), type_(Type::
GetType())
195 template<
typename MessageType,
typename Type = std::decay_t<MessageType>,
196 typename std::enable_if_t<traits::is_message_type<Type>::value,
int> = 0>
199 if (this->msg_ && this->type_ == Type::GetType())
201 static_cast<Type&
>(*this->msg_) = std::forward<MessageType>(m);
205 this->msg_ = std::make_unique<Type>(std::forward<MessageType>(m));
206 this->type_ = Type::GetType();
231 if (!this->msg_)
throw std::runtime_error(
"MessageElement is empty");
232 return this->msg_->allowSend();
244 if (!this->msg_)
throw std::runtime_error(
"MessageElement is empty");
245 return this->msg_->valid();
255 template<
typename MessageType> MessageType&
as()
257 type_check_<MessageType>();
259 if (!this->msg_)
throw std::runtime_error(
"MessageElement is empty");
260 if (this->type_ != MessageType::GetType())
262 return static_cast<MessageType&
>(*this->msg_);
265 template<
typename MessageType>
const MessageType&
as()
const
267 type_check_<std::decay_t<MessageType>>();
269 if (!this->msg_)
throw std::runtime_error(
"MessageElement is empty");
270 if (this->type_ != MessageType::GetType())
272 return static_cast<const MessageType&
>(*this->msg_);
284 template<
typename Callable>
auto visit(Callable&& f)
286 return this->visit_(std::make_index_sequence<
MessageTypesList.size()>{}, std::forward<Callable>(f));
289 template<
typename Callable>
auto visit(Callable&& f)
const
291 return this->cvisit_(std::make_index_sequence<
MessageTypesList.size()>{}, std::forward<Callable>(f));
346 bool empty() const noexcept {
return this->message_.empty(); }
353 void clear() noexcept {
return this->message_.clear(); }
356 void pop_back() {
return this->message_.pop_back(); }
394 type_check_<std::decay_t<MessageType>>();
411 type_check_<MessageType>();
413 this->message_.emplace_back(std::in_place_type_t<MessageType>{}, std::forward<Args>(args)...);
428 return this->emplace_back<GetType_t<Type>>(std::forward<Args>(args)...);
442 type_check_<std::decay_t<MessageType>>();
444 return this->message_.insert(pos,
MessageElement(std::forward<MessageType>(m)));
459 type_check_<MessageType>();
460 return this->message_.emplace(pos, std::in_place_type_t<MessageType>{}, std::forward<Args>(args)...);
474 return this->emplace<GetType_t<Type>>(pos, std::forward<Args>(args)...);
488 template<
typename MessageType>
490 -> std::enable_if_t<traits::is_message_type<std::decay_t<MessageType>>::value,
MessageChain&>
504 template<
typename MessageType>
506 -> std::enable_if_t<traits::is_message_type<std::decay_t<MessageType>>::value,
MessageChain>
511 template<
typename MessageType>
513 -> std::enable_if_t<traits::is_message_type<std::decay_t<MessageType>>::value,
MessageChain>
531 template<
typename MessageType> MessageType&
GetAt(
size_type i) {
return this->message_.at(i).as<MessageType>(); }
535 return this->message_.at(i).as<MessageType>();
554 return this->GetAt<GetType_t<Type>>(i);
574 template<
typename MessageType> std::vector<MessageType>
GetAll()
const
576 type_check_<MessageType>();
578 std::vector<MessageType> v;
579 for (
const auto& p : this->message_)
581 if (p.type() == MessageType::GetType()) v.push_back(p.as<MessageType>());
593 template<MessageTypes Type>
auto GetAll()
const {
return this->GetAll<GetType_t<Type>>(); }
603 template<
typename MessageType> std::vector<std::reference_wrapper<MessageType>>
GetAllRef()
605 type_check_<MessageType>();
607 std::vector<std::reference_wrapper<MessageType>> v;
608 for (
auto& p : this->message_)
610 if (p.type() == MessageType::GetType()) v.push_back(std::ref(p.as<MessageType>()));
615 template<
typename MessageType> std::vector<std::reference_wrapper<const MessageType>>
GetAllRef()
const
617 type_check_<MessageType>();
619 std::vector<std::reference_wrapper<const MessageType>> v;
620 for (
const auto& p : this->message_)
622 if (p.type() == MessageType::GetType()) v.push_back(std::cref(p.as<MessageType>()));
637 template<MessageTypes Type>
auto GetAllRef() {
return this->GetAllRef<GetType_t<Type>>(); }
639 template<MessageTypes Type>
auto GetAllRef()
const {
return this->GetAllRef<GetType_t<Type>>(); }
673 return this->emplace_back<AppMessage>(std::forward<Args>(args)...);
679 return this->emplace_back<AtAllMessage>(std::forward<Args>(args)...);
685 return this->emplace_back<AtMessage>(std::forward<Args>(args)...);
691 return this->emplace_back<AudioMessage>(std::forward<Args>(args)...);
697 return this->emplace_back<DiceMessage>(std::forward<Args>(args)...);
703 return this->emplace_back<FaceMessage>(std::forward<Args>(args)...);
709 return this->emplace_back<FlashImageMessage>(std::forward<Args>(args)...);
715 return this->emplace_back<ImageMessage>(std::forward<Args>(args)...);
721 return this->emplace_back<JsonMessage>(std::forward<Args>(args)...);
727 return this->emplace_back<MiraiCodeMessage>(std::forward<Args>(args)...);
733 return this->emplace_back<PlainMessage>(std::forward<Args>(args)...);
739 return this->emplace_back<PokeMessage>(std::forward<Args>(args)...);
745 return this->emplace_back<XmlMessage>(std::forward<Args>(args)...);
751 return this->emplace_back<ForwardMessage>(std::forward<Args>(args)...);
Common interface for all message types
MessageElement()=default
Constructors, conversion operators and destructor
MessageElement & operator=(const MessageElement &rhs)
Constructors, conversion operators and destructor
MessageElement(std::in_place_type_t< MessageType >, Args &&... args)
Constructors, conversion operators and destructor
MessageElement & operator=(std::unique_ptr< IMessage > &&msg)
Constructors, conversion operators and destructor
bool allowSend() const
检查消息是否可以用于发送
auto visit(Callable &&f)
对此消息元素应用visitor,类似 std::visit
MessageElement(const MessageElement &rhs)
Constructors, conversion operators and destructor
MessageElement(MessageType &&m)
Constructors, conversion operators and destructor
MessageElement & operator=(MessageType &&m)
Constructors, conversion operators and destructor
MessageTypes type() const
获取所含消息的类型
MessageType & as()
转换为某一特定类型的消息,类型错误时将抛出异常
bool valid() const
检查消息是否有效
const MessageType & as() const
转换为某一特定类型的消息,类型错误时将抛出异常
MessageElement(MessageElement &&) noexcept=default
Constructors, conversion operators and destructor
MessageElement(IMessage *m)
Constructors, conversion operators and destructor
auto visit(Callable &&f) const
对此消息元素应用visitor,类似 std::visit
MessageElement(std::unique_ptr< IMessage > &&msg)
Constructors, conversion operators and destructor
MessageContainer::difference_type difference_type
STL-like interface
iterator erase(const_iterator first, const_iterator last)
STL-like interface
std::vector< MessageType > GetAll() const
获取所有指定类型的消息元素
reverse_iterator rbegin() noexcept
STL-like interface
MessageChain & operator+=(const MessageChain &rhs)
MessageChain & Audio(Args &&... args)
在消息链结尾构造 AudioMessage,返回自身的引用
MessageTypes GetType(size_type i) const
获取指定下标处的消息类型
reverse_iterator rend() noexcept
STL-like interface
bool empty() const noexcept
STL-like interface
const MessageType & GetAt(size_type i) const
获取指定下标处的消息
const_reference front() const
STL-like interface
auto GetAllRef()
获取所有指定类型的消息元素的引用
void shrink_to_fit() noexcept
STL-like interface
friend auto operator+(MessageType &&m, const MessageChain &rhs) -> std::enable_if_t< traits::is_message_type< std::decay_t< MessageType > >::value, MessageChain >
GetType_t< Type > & GetAt(size_type i)
获取指定下标处的消息
MessageContainer::const_reverse_iterator const_reverse_iterator
STL-like interface
void resize(size_type count)
STL-like interface
MessageContainer::const_iterator const_iterator
STL-like interface
MessageContainer::pointer pointer
STL-like interface
const_iterator cbegin() const noexcept
STL-like interface
const_reference back() const
STL-like interface
size_type size() const noexcept
STL-like interface
MessageContainer::allocator_type allocator_type
STL-like interface
MessageChain & At(Args &&... args)
在消息链结尾构造 AtMessage,返回自身的引用
std::vector< MessageElement > MessageContainer
const_iterator begin() const noexcept
STL-like interface
MessageChain & Xml(Args &&... args)
在消息链结尾构造 XmlMessage,返回自身的引用
iterator insert(const_iterator pos, MessageType &&m)
在消息链中插入元素
MessageChain & Json(Args &&... args)
在消息链结尾构造 JsonMessage,返回自身的引用
const_iterator cend() const noexcept
STL-like interface
MessageContainer::const_reference const_reference
STL-like interface
MessageChain & Poke(Args &&... args)
在消息链结尾构造 PokeMessage,返回自身的引用
iterator begin() noexcept
STL-like interface
MessageChain & Flash(Args &&... args)
在消息链结尾构造 FlashImageMessage,返回自身的引用
const_reverse_iterator crend() const noexcept
STL-like interface
reference at(size_type n)
STL-like interface
std::vector< std::reference_wrapper< const MessageType > > GetAllRef() const
获取所有指定类型的消息元素的引用
MessageContainer message_
auto GetAll() const
获取所有指定类型的消息元素
size_type max_size() const noexcept
STL-like interface
iterator erase(const_iterator pos)
STL-like interface
void clear() noexcept
STL-like interface
MessageContainer::reverse_iterator reverse_iterator
STL-like interface
MessageContainer::size_type size_type
STL-like interface
std::optional< SourceInfo > GetSourceInfo() const
获取消息链中的来源信息
MessageType & GetAt(size_type i)
获取指定下标处的消息
size_type capacity() const noexcept
STL-like interface
MessageChain & Forward(Args &&... args)
在消息链结尾插入 ForwardMessage,返回自身的引用
const_reference operator[](size_type n) const noexcept
STL-like interface
bool valid() const
检查消息链是否有效
iterator end() noexcept
STL-like interface
void pop_back()
STL-like interface
MessageChain & AtAll(Args &&... args)
在消息链结尾构造 AtAllMessage,返回自身的引用
std::vector< std::reference_wrapper< MessageType > > GetAllRef()
获取所有指定类型的消息元素的引用
reference front()
STL-like interface
MessageChain & App(Args &&... args)
在消息链结尾构造 AppMessage,返回自身的引用
MessageChain & Dice(Args &&... args)
在消息链结尾构造 DiceMessage,返回自身的引用
MessageChain & Plain(Args &&... args)
在消息链结尾构造 PlainMessage,返回自身的引用
MessageContainer::iterator iterator
STL-like interface
const_iterator end() const noexcept
STL-like interface
MessageChain(const MessageChain &rhs)
const_reverse_iterator crbegin() const noexcept
STL-like interface
void reserve(size_type new_cap)
STL-like interface
reference back()
STL-like interface
const_reference at(size_type n) const
STL-like interface
MessageChain & operator=(const MessageChain &rhs)
iterator emplace(const_iterator pos, Args &&... args)
在消息链中插入元素
reference operator[](size_type n) noexcept
STL-like interface
MessageContainer::value_type value_type
STL-like interface
friend auto operator+(const MessageChain &lhs, MessageType &&m) -> std::enable_if_t< traits::is_message_type< std::decay_t< MessageType > >::value, MessageChain >
void RemoveInvalid()
去除消息链中的无效消息
MessageChain & MiraiCode(Args &&... args)
在消息链结尾构造 MiraiCodeMessage,返回自身的引用
friend MessageChain operator+(const MessageChain &lhs, const MessageChain &rhs)
拼接两个消息链
MessageContainer::const_pointer const_pointer
STL-like interface
MessageChain & Face(Args &&... args)
在消息链结尾构造 FaceMessage,返回自身的引用
const GetType_t< Type > & GetAt(size_type i) const
获取指定下标处的消息
auto GetAllRef() const
获取所有指定类型的消息元素的引用
auto operator+=(MessageType &&m) -> std::enable_if_t< traits::is_message_type< std::decay_t< MessageType > >::value, MessageChain & >
MessageChain & emplace_back(Args &&... args)
在消息链结尾直接构造消息元素
MessageChain & push_back(MessageType &&m)
在消息链结尾添加消息元素
MessageContainer::reference reference
STL-like interface
friend MessageChain operator+(const MessageElement &m, const MessageChain &rhs)
MessageChain & Image(Args &&... args)
在消息链结尾构造 ImageMessage,返回自身的引用
std::string to_string(EventTypes type)
MessageChain::MessageElement MessageElement
int64_t MessageId_t
消息id类型,用于撤回消息和引用消息
typename GetType< type >::type GetType_t
constexpr std::array< MessageTypes, static_cast< size_t >(MessageTypes::ENUM_END)> MessageTypesList