Add streams
This commit is contained in:
parent
030f69c66d
commit
84abbe8178
3 changed files with 149 additions and 20 deletions
|
@ -1,50 +1,61 @@
|
||||||
module;
|
#pragma once
|
||||||
c export module larra.library.stream;
|
#include <larra/jid.hpp>
|
||||||
export import larra.library.jid;
|
#include <pugixml.hpp>
|
||||||
import larra.library.utils;
|
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace larra::xmpp {
|
namespace larra::xmpp {
|
||||||
|
|
||||||
export struct Stream {
|
namespace impl {
|
||||||
std::optional<BareJid> from;
|
|
||||||
std::optional<BareJid> to;
|
template <bool JidFrom, bool JidTo>
|
||||||
|
struct BasicStream {
|
||||||
|
static constexpr bool kJidFrom = JidFrom;
|
||||||
|
static constexpr bool kJidTo = JidTo;
|
||||||
|
using FromType = std::optional<std::conditional_t<JidFrom, BareJid, std::string>>;
|
||||||
|
using ToType = std::optional<std::conditional_t<JidTo, BareJid, std::string>>;
|
||||||
|
FromType from;
|
||||||
|
ToType to;
|
||||||
std::optional<std::string> id;
|
std::optional<std::string> id;
|
||||||
std::optional<std::string> version;
|
std::optional<std::string> version;
|
||||||
std::optional<std::string> xmlLang;
|
std::optional<std::string> xmlLang;
|
||||||
|
|
||||||
template <typename Self>
|
template <typename Self>
|
||||||
constexpr auto From(this Self&& self, BareJid value) {
|
constexpr auto From(this Self&& self, FromType value) {
|
||||||
return utils::FieldSetHelper::With<"from">(std::forward<Self>(self), std::move(value));
|
return utils::FieldSetHelper::With<"from">(std::forward<Self>(self), std::move(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Self>
|
template <typename Self>
|
||||||
constexpr auto To(this Self&& self, BareJid value) {
|
constexpr auto To(this Self&& self, ToType value) {
|
||||||
return utils::FieldSetHelper::With<"to">(std::forward<Self>(self), std::move(value));
|
return utils::FieldSetHelper::With<"to">(std::forward<Self>(self), std::move(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Self>
|
template <typename Self>
|
||||||
constexpr auto Id(this Self&& self, std::string value) {
|
constexpr auto Id(this Self&& self, std::optional<std::string> value) {
|
||||||
return utils::FieldSetHelper::With<"id">(std::forward<Self>(self), std::move(value));
|
return utils::FieldSetHelper::With<"id">(std::forward<Self>(self), std::move(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Self>
|
template <typename Self>
|
||||||
constexpr auto Version(this Self&& self, std::string value) {
|
constexpr auto Version(this Self&& self, std::optional<std::string> value) {
|
||||||
return utils::FieldSetHelper::With<"version">(std::forward<Self>(self), std::move(value));
|
return utils::FieldSetHelper::With<"version">(std::forward<Self>(self), std::move(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Self>
|
template <typename Self>
|
||||||
constexpr auto XmlLang(this Self&& self, std::string value) {
|
constexpr auto XmlLang(this Self&& self, std::optional<std::string> value) {
|
||||||
return utils::FieldSetHelper::With<"xmlLang">(std::forward<Self>(self), std::move(value));
|
return utils::FieldSetHelper::With<"xmlLang">(std::forward_like<Self>(self), std::move(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr Stream(BareJid to) : to(std::move(to)), version("1.0") {};
|
auto SerializeStream(pugi::xml_node& node) const -> void;
|
||||||
friend auto operator<<(pugi::xml_node& node, const Stream& stream) {
|
friend auto operator<<(pugi::xml_node& node, const BasicStream<JidFrom, JidTo>& stream) -> pugi::xml_node& {
|
||||||
if(stream.from) {
|
return (stream.SerializeStream(node), node);
|
||||||
auto str = ToString(*stream.from);
|
|
||||||
node.append_attribute("from") = str.c_str();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
static auto Parse(const pugi::xml_node& node) -> BasicStream<JidFrom, JidTo>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
using UserStream = impl::BasicStream<true, false>;
|
||||||
|
using UserToUserStream = impl::BasicStream<true, true>;
|
||||||
|
|
||||||
|
using ServerStream = impl::BasicStream<false, false>;
|
||||||
|
using ServerToUserStream = impl::BasicStream<false, true>;
|
||||||
|
|
||||||
} // namespace larra::xmpp
|
} // namespace larra::xmpp
|
||||||
|
|
64
library/src/stream.cpp
Normal file
64
library/src/stream.cpp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#include <larra/stream.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
inline auto ToOptionalString(const pugi::xml_attribute& attribute) -> std::optional<std::string> {
|
||||||
|
return attribute ? std::optional{std::string{attribute.as_string()}} : std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool IsJid>
|
||||||
|
inline auto ToOptionalUser(const pugi::xml_attribute& attribute) {
|
||||||
|
if constexpr(IsJid) {
|
||||||
|
return attribute ? std::optional{larra::xmpp::BareJid::Parse(attribute.as_string())} : std::nullopt;
|
||||||
|
} else {
|
||||||
|
return attribute ? std::optional{std::string{attribute.as_string()}} : std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ToString(std::string data) -> std::string {
|
||||||
|
return std::move(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace larra::xmpp {
|
||||||
|
|
||||||
|
template <bool JidFrom, bool JidTo>
|
||||||
|
auto impl::BasicStream<JidFrom, JidTo>::SerializeStream(pugi::xml_node& node) const -> void {
|
||||||
|
if(this->from) {
|
||||||
|
node.append_attribute("from") = ToString(*this->from).c_str();
|
||||||
|
}
|
||||||
|
if(this->to) {
|
||||||
|
node.append_attribute("to") = ToString(*this->to).c_str();
|
||||||
|
}
|
||||||
|
if(this->id) {
|
||||||
|
node.append_attribute("id") = this->id->c_str();
|
||||||
|
}
|
||||||
|
if(this->version) {
|
||||||
|
node.append_attribute("version") = this->version->c_str();
|
||||||
|
}
|
||||||
|
if(this->xmlLang) {
|
||||||
|
node.append_attribute("xml:lang") = this->xmlLang->c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template auto ServerStream::SerializeStream(pugi::xml_node& node) const -> void;
|
||||||
|
template auto ServerToUserStream::SerializeStream(pugi::xml_node& node) const -> void;
|
||||||
|
|
||||||
|
template auto UserToUserStream::SerializeStream(pugi::xml_node& node) const -> void;
|
||||||
|
template auto UserStream::SerializeStream(pugi::xml_node& node) const -> void;
|
||||||
|
|
||||||
|
template <bool JidFrom, bool JidTo>
|
||||||
|
auto impl::BasicStream<JidFrom, JidTo>::Parse(const pugi::xml_node& node) -> impl::BasicStream<JidFrom, JidTo> {
|
||||||
|
return {ToOptionalUser<JidFrom>(node.attribute("from")),
|
||||||
|
ToOptionalUser<JidTo>(node.attribute("to")),
|
||||||
|
ToOptionalString(node.attribute("id")),
|
||||||
|
ToOptionalString(node.attribute("version")),
|
||||||
|
ToOptionalString(node.attribute("xml:lang"))};
|
||||||
|
}
|
||||||
|
template auto UserStream::Parse(const pugi::xml_node& node) -> UserStream;
|
||||||
|
template auto UserToUserStream::Parse(const pugi::xml_node& node) -> UserToUserStream;
|
||||||
|
|
||||||
|
template auto ServerStream::Parse(const pugi::xml_node& node) -> ServerStream;
|
||||||
|
template auto ServerToUserStream::Parse(const pugi::xml_node& node) -> ServerToUserStream;
|
||||||
|
} // namespace larra::xmpp
|
54
tests/stream.cpp
Normal file
54
tests/stream.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <larra/stream.hpp>
|
||||||
|
|
||||||
|
namespace larra::xmpp {
|
||||||
|
|
||||||
|
constexpr std::string_view kSerializedData =
|
||||||
|
R"(<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' xml:lang='en' version='1.0' id='abc' from='user@example.com' />
|
||||||
|
)";
|
||||||
|
|
||||||
|
constexpr std::string_view kCheckSerializeData =
|
||||||
|
R"(<stream:stream from="user@example.com" to="anotheruser@example.com" id="abc" version="1.0" xml:lang="en" />
|
||||||
|
)";
|
||||||
|
|
||||||
|
TEST(Stream, Serialize) {
|
||||||
|
UserToUserStream originalStream;
|
||||||
|
originalStream.from = BareJid{"user", "example.com"};
|
||||||
|
originalStream.to = BareJid{"anotheruser", "example.com"};
|
||||||
|
originalStream.id = "abc";
|
||||||
|
originalStream.version = "1.0";
|
||||||
|
originalStream.xmlLang = "en";
|
||||||
|
|
||||||
|
pugi::xml_document doc;
|
||||||
|
pugi::xml_node streamNode = doc.append_child("stream:stream");
|
||||||
|
streamNode << originalStream;
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
doc.child("stream:stream").print(oss, "\t");
|
||||||
|
const std::string serializedData = oss.str();
|
||||||
|
|
||||||
|
ASSERT_EQ(serializedData, kCheckSerializeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Stream, Deserialize) {
|
||||||
|
pugi::xml_document parsedDoc;
|
||||||
|
parsedDoc.load_string(kSerializedData.data());
|
||||||
|
|
||||||
|
const UserStream deserializedStream = UserStream::Parse(parsedDoc.child("stream:stream"));
|
||||||
|
ASSERT_TRUE(deserializedStream.from.has_value());
|
||||||
|
ASSERT_EQ(ToString(*deserializedStream.from), "user@example.com");
|
||||||
|
|
||||||
|
ASSERT_FALSE(deserializedStream.to.has_value());
|
||||||
|
|
||||||
|
ASSERT_TRUE(deserializedStream.id.has_value());
|
||||||
|
ASSERT_EQ(deserializedStream.id.value(), "abc");
|
||||||
|
|
||||||
|
ASSERT_TRUE(deserializedStream.version.has_value());
|
||||||
|
ASSERT_EQ(deserializedStream.version.value(), "1.0");
|
||||||
|
|
||||||
|
ASSERT_TRUE(deserializedStream.xmlLang.has_value());
|
||||||
|
ASSERT_EQ(deserializedStream.xmlLang.value(), "en");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace larra::xmpp
|
Loading…
Reference in a new issue