Update Jid
This commit is contained in:
parent
52ec88216c
commit
945b44e0e4
3 changed files with 153 additions and 71 deletions
182
src/lib/jid.cpp
182
src/lib/jid.cpp
|
@ -4,72 +4,144 @@ import fmt;
|
||||||
|
|
||||||
namespace larra::xmpp {
|
namespace larra::xmpp {
|
||||||
|
|
||||||
export struct Jid {
|
export struct BareJid;
|
||||||
[[nodiscard]] static auto Parse(std::string_view jid) -> Jid {
|
|
||||||
Jid response;
|
auto ParseBareJid(std::string_view, std::size_t) -> BareJid;
|
||||||
|
|
||||||
|
export struct BareJid {
|
||||||
|
std::string username;
|
||||||
|
std::string server;
|
||||||
|
|
||||||
|
[[nodiscard]] friend auto ToString(const BareJid& jid) -> std::string {
|
||||||
|
return std::format("{}@{}", jid.username, jid.server);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
[[nodiscard]] auto Username(this Self&& self, std::string username) -> BareJid {
|
||||||
|
return {std::move(username), std::forward_like<Self>(self.resource)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
[[nodiscard]] auto Server(this Self&& self, std::string server) -> BareJid {
|
||||||
|
return {std::forward_like<Self>(self.server), std::move(server)};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static auto Parse(std::string_view jid) -> BareJid {
|
||||||
const auto at = jid.find('@');
|
const auto at = jid.find('@');
|
||||||
const auto slash = jid.find('/', at == std::string_view::npos ? 0 : at);
|
if(at == std::string_view::npos) {
|
||||||
|
throw std::invalid_argument("Invalid string for jid");
|
||||||
if(at != std::string_view::npos) {
|
|
||||||
response.username = jid.substr(0, at);
|
|
||||||
response.server = jid.substr(at + 1, (slash == std::string_view::npos ? jid.size() : slash) - (at + 1));
|
|
||||||
} else {
|
|
||||||
response.server = jid.substr(0, slash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(slash != std::string_view::npos) {
|
return ParseBareJid(jid, at);
|
||||||
response.resource = jid.substr(slash + 1);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return response;
|
auto ParseBareJid(std::string_view jid, std::size_t at) -> BareJid {
|
||||||
}
|
return {static_cast<std::string>(jid.substr(0, at)), static_cast<std::string>(jid.substr(at + 1))};
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Self>
|
export struct BareResourceJid;
|
||||||
[[nodiscard]] auto Username(this Self&& self, std::string username) -> Jid {
|
|
||||||
return {std::forward_like<Self>(self.server), std::move(username), std::forward_like<Self>(self.resource)};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Self>
|
auto ParseBareResourceJid(std::string_view, std::size_t) -> BareResourceJid;
|
||||||
[[nodiscard]] auto Server(this Self&& self, std::string server) -> Jid {
|
|
||||||
return {std::move(server), std::forward_like<Self>(self.username), std::forward_like<Self>(self.resource)};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Self>
|
export struct BareResourceJid {
|
||||||
[[nodiscard]] auto Resource(this Self&& self, std::string resource) -> Jid {
|
std::string server;
|
||||||
return {std::forward_like<Self>(self.server), std::forward_like<Self>(self.username), std::move(resource)};
|
std::string resource;
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto IsValid() const -> bool {
|
[[nodiscard]] friend auto ToString(const BareResourceJid& jid) -> std::string {
|
||||||
return this->server && this->username || this->resource;
|
return std::format("{}/{}", jid.server, jid.resource);
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Username() const -> std::string_view {
|
|
||||||
return *this->username;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Server() const -> std::string_view {
|
|
||||||
return *this->server;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Resource() const -> std::string_view {
|
|
||||||
return *this->resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] explicit operator std::string() const {
|
|
||||||
if(!IsValid()) {
|
|
||||||
throw std::invalid_argument("Invalid jid obj");
|
|
||||||
}
|
|
||||||
return !this->username ? std::format("{}/{}", *this->server, *this->resource)
|
|
||||||
: !this->resource ? std::format("{}@{}", *this->username, *this->server)
|
|
||||||
: std::format("{}@{}/{}", *this->username, *this->server, *this->resource);
|
|
||||||
}
|
|
||||||
[[nodiscard]] auto ToString() const -> std::string {
|
|
||||||
return static_cast<std::string>(*this);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<std::string> server{};
|
template <typename Self>
|
||||||
std::optional<std::string> username{};
|
[[nodiscard]] auto Server(this Self&& self, std::string server) -> BareResourceJid {
|
||||||
std::optional<std::string> resource{};
|
return {std::move(server), std::forward_like<Self>(self.resource)};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
[[nodiscard]] auto Resource(this Self&& self, std::string resource) -> BareResourceJid {
|
||||||
|
return {std::forward_like<Self>(self.server), std::move(resource)};
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] static auto Parse(std::string_view jid) -> BareResourceJid {
|
||||||
|
const auto slash = jid.find('/');
|
||||||
|
if(slash == std::string_view::npos) {
|
||||||
|
throw std::invalid_argument("Invalid string for jid");
|
||||||
|
};
|
||||||
|
|
||||||
|
return ParseBareResourceJid(jid, slash);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
auto ParseBareResourceJid(std::string_view jid, std::size_t slash) -> BareResourceJid {
|
||||||
|
return {static_cast<std::string>(jid.substr(0, slash)), static_cast<std::string>(jid.substr(slash + 1))};
|
||||||
|
}
|
||||||
|
|
||||||
|
export struct FullJid;
|
||||||
|
|
||||||
|
auto ParseFullJid(std::string_view jid, std::size_t at, std::size_t slash) -> FullJid;
|
||||||
|
|
||||||
|
export struct FullJid {
|
||||||
|
std::string username;
|
||||||
|
std::string server;
|
||||||
|
std::string resource;
|
||||||
|
|
||||||
|
[[nodiscard]] friend auto ToString(const FullJid& jid) -> std::string {
|
||||||
|
return std::format("{}@{}/{}", jid.username, jid.server, jid.resource);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
[[nodiscard]] auto Username(this Self&& self, std::string username) -> FullJid {
|
||||||
|
return {std::move(username), std::forward_like<Self>(self.server), std::forward_like<Self>(self.resource)};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
[[nodiscard]] auto Server(this Self&& self, std::string server) -> FullJid {
|
||||||
|
return {std::forward_like<Self>(self.username), std::move(server), std::forward_like<Self>(self.resource)};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Self>
|
||||||
|
[[nodiscard]] auto Resource(this Self&& self, std::string resource) -> FullJid {
|
||||||
|
return {std::forward_like<Self>(self.username), std::forward_like<Self>(self.server), std::move(resource)};
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] static auto Parse(std::string_view jid) -> FullJid {
|
||||||
|
const auto at = jid.find('@');
|
||||||
|
const auto slash = jid.find('/', at);
|
||||||
|
if(at == std::string_view::npos || slash == std::string_view::npos) {
|
||||||
|
throw std::invalid_argument("Invalid string for jid");
|
||||||
|
};
|
||||||
|
|
||||||
|
return ParseFullJid(jid, at, slash);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
auto ParseFullJid(std::string_view jid, std::size_t at, std::size_t slash) -> FullJid {
|
||||||
|
return {static_cast<std::string>(jid.substr(0, at)),
|
||||||
|
static_cast<std::string>(jid.substr(at + 1, slash - at - 1)),
|
||||||
|
static_cast<std::string>(jid.substr(slash + 1))};
|
||||||
|
}
|
||||||
|
using JidVariant = std::variant<BareJid, BareResourceJid, FullJid>;
|
||||||
|
|
||||||
|
export struct Jid : JidVariant {
|
||||||
|
using JidVariant::variant;
|
||||||
|
[[nodiscard]] static auto Parse(std::string_view jid) -> Jid {
|
||||||
|
const auto at = jid.find('@');
|
||||||
|
const auto slash = jid.find('/', at == std::string_view::npos ? 0 : at);
|
||||||
|
if(at == std::string_view::npos) {
|
||||||
|
return ParseBareResourceJid(jid, slash);
|
||||||
|
}
|
||||||
|
if(slash == std::string_view::npos) {
|
||||||
|
return ParseBareJid(jid, at);
|
||||||
|
}
|
||||||
|
return ParseFullJid(jid, at, slash);
|
||||||
|
}
|
||||||
|
[[nodiscard]] friend auto ToString(const Jid& jid) -> std::string {
|
||||||
|
return std::visit<std::string>(
|
||||||
|
[](const auto& jid) -> std::string {
|
||||||
|
return ToString(jid);
|
||||||
|
},
|
||||||
|
jid);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace larra::xmpp
|
} // namespace larra::xmpp
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
export module larra.library;
|
export module larra.library;
|
||||||
export import larra.jid;
|
export import larra.library.jid;
|
||||||
|
|
|
@ -6,32 +6,42 @@ import larra.library.jid;
|
||||||
namespace larra::xmpp {
|
namespace larra::xmpp {
|
||||||
|
|
||||||
TEST(Jid, Basic) {
|
TEST(Jid, Basic) {
|
||||||
auto jid = Jid{.username = "user"};
|
auto jid = FullJid{.username = "user"};
|
||||||
EXPECT_FALSE(jid.IsValid());
|
|
||||||
|
|
||||||
const auto jid2 = std::move(jid).Server("server").Resource("resource");
|
const auto jid2 = std::move(jid).Server("server").Resource("resource");
|
||||||
EXPECT_EQ(jid2.Server(), "server");
|
EXPECT_EQ(jid2.server, "server");
|
||||||
EXPECT_EQ(jid2.Username(), "user");
|
EXPECT_EQ(jid2.username, "user");
|
||||||
EXPECT_EQ(jid2.Resource(), "resource");
|
EXPECT_EQ(jid2.resource, "resource");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Jid, Parse) {
|
TEST(Jid, Parse) {
|
||||||
const auto jid = Jid::Parse("user@server/resource");
|
const auto jid = Jid::Parse("user@server/resource");
|
||||||
EXPECT_EQ(jid.Username(), "user");
|
|
||||||
EXPECT_EQ(jid.Server(), "server");
|
EXPECT_TRUE(std::get_if<FullJid>(&jid));
|
||||||
EXPECT_EQ(jid.Resource(), "resource");
|
const auto& fullJid = std::get<FullJid>(jid);
|
||||||
|
EXPECT_EQ(fullJid.username, "user");
|
||||||
|
EXPECT_EQ(fullJid.server, "server");
|
||||||
|
EXPECT_EQ(fullJid.resource, "resource");
|
||||||
|
|
||||||
const auto jid2 = Jid::Parse("server/resource");
|
const auto jid2 = Jid::Parse("server/resource");
|
||||||
EXPECT_EQ(jid2.Server(), "server");
|
|
||||||
EXPECT_EQ(jid2.Resource(), "resource");
|
EXPECT_TRUE(std::get_if<BareResourceJid>(&jid2));
|
||||||
|
const auto& resourceJid = std::get<BareResourceJid>(jid2);
|
||||||
|
EXPECT_EQ(resourceJid.server, "server");
|
||||||
|
EXPECT_EQ(resourceJid.resource, "resource");
|
||||||
|
|
||||||
const auto jid3 = Jid::Parse("user@server");
|
const auto jid3 = Jid::Parse("user@server");
|
||||||
EXPECT_EQ(jid3.Username(), "user");
|
|
||||||
EXPECT_EQ(jid3.Server(), "server");
|
EXPECT_TRUE(std::get_if<BareJid>(&jid3));
|
||||||
|
const auto& bareJid = std::get<BareJid>(jid3);
|
||||||
|
EXPECT_EQ(bareJid.username, "user");
|
||||||
|
EXPECT_EQ(bareJid.server, "server");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Jid, ToString) {
|
TEST(Jid, ToString) {
|
||||||
EXPECT_EQ((Jid{.server = "server", .username = "user", .resource = "resource"}.ToString()), "user@server/resource");
|
EXPECT_EQ(ToString(FullJid{.username = "user", .server = "server", .resource = "resource"}), "user@server/resource");
|
||||||
EXPECT_EQ((Jid{.server = "server", .username = "user"}.ToString()), "user@server");
|
EXPECT_EQ(ToString(BareJid{.username = "user", .server = "server"}), "user@server");
|
||||||
EXPECT_THROW(std::ignore = Jid{}.ToString(), std::invalid_argument);
|
EXPECT_EQ(ToString(BareResourceJid{.server = "server", .resource = "resource"}), "server/resource");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace larra::xmpp
|
} // namespace larra::xmpp
|
||||||
|
|
Loading…
Reference in a new issue