export module larra.library.jid; import std; import fmt; namespace larra::xmpp { export struct BareJid; 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 [[nodiscard]] auto Username(this Self&& self, std::string username) -> BareJid { return {std::move(username), std::forward_like(self.resource)}; } template [[nodiscard]] auto Server(this Self&& self, std::string server) -> BareJid { return {std::forward_like(self.server), std::move(server)}; } [[nodiscard]] static auto Parse(std::string_view jid) -> BareJid { const auto at = jid.find('@'); if(at == std::string_view::npos) { throw std::invalid_argument("Invalid string for jid"); } return ParseBareJid(jid, at); } }; auto ParseBareJid(std::string_view jid, std::size_t at) -> BareJid { return {static_cast(jid.substr(0, at)), static_cast(jid.substr(at + 1))}; } export struct BareResourceJid; auto ParseBareResourceJid(std::string_view, std::size_t) -> BareResourceJid; export struct BareResourceJid { std::string server; std::string resource; [[nodiscard]] friend auto ToString(const BareResourceJid& jid) -> std::string { return std::format("{}/{}", jid.server, jid.resource); }; template [[nodiscard]] auto Server(this Self&& self, std::string server) -> BareResourceJid { return {std::move(server), std::forward_like(self.resource)}; }; template [[nodiscard]] auto Resource(this Self&& self, std::string resource) -> BareResourceJid { return {std::forward_like(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(jid.substr(0, slash)), static_cast(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 [[nodiscard]] auto Username(this Self&& self, std::string username) -> FullJid { return {std::move(username), std::forward_like(self.server), std::forward_like(self.resource)}; }; template [[nodiscard]] auto Server(this Self&& self, std::string server) -> FullJid { return {std::forward_like(self.username), std::move(server), std::forward_like(self.resource)}; }; template [[nodiscard]] auto Resource(this Self&& self, std::string resource) -> FullJid { return {std::forward_like(self.username), std::forward_like(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(jid.substr(0, at)), static_cast(jid.substr(at + 1, slash - at - 1)), static_cast(jid.substr(slash + 1))}; } using JidVariant = std::variant; 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( [](const auto& jid) -> std::string { return ToString(jid); }, jid); }; }; } // namespace larra::xmpp