#pragma once #include namespace roro::gemini { // A URL split per RFC 3986 (appendix B). For Gemini, the host is lower-cased and the port // defaults to 1965. struct Url { std::string scheme, authority, host, path, query, fragment; int port = -1; bool hasAuthority = false, hasQuery = false, hasFragment = false; int portOrDefault() const { return port > 0 ? port : 1965; } }; // False unless it has a scheme and a host: only absolute URLs are fetched. bool parseUrl(const std::string& text, Url& out); bool isGemini(const std::string& url); // `ref` against `base`, per RFC 3986 section 5.2 (dot segments included). std::string resolve(const std::string& base, const std::string& ref); // What goes on the wire: no fragment, lower-case host, never an empty path. std::string requestUrl(const std::string& url); // For input prompts: everything but unreserved characters percent-encoded (UTF-8 bytes). std::string encodeQuery(const std::string& text); // Where a Saved Page lives (Q82): /gemini/saved/[_]/[~].gmi std::string savedPath(const std::string& url); } // namespace roro::gemini