[libc++] Implement `operator<=>` for `filesystem::directory_entry`

Implements part of P1614R2 "The Mothership has Landed"

Differential Revision: https://reviews.llvm.org/D130860

NOKEYCHECK=True
GitOrigin-RevId: f1974f039fa76316721a2228b3241f17489f6f7b
diff --git a/include/filesystem b/include/filesystem
index 8b81e10..086d597 100644
--- a/include/filesystem
+++ b/include/filesystem
@@ -164,7 +164,73 @@
       path u8path(InputIterator first, InputIterator last);
 
     class filesystem_error;
-    class directory_entry;
+
+    class directory_entry {
+    public:
+      directory_entry() noexcept = default;
+      directory_entry(const directory_entry&) = default;
+      directory_entry(directory_entry&&) noexcept = default;
+      explicit directory_entry(const filesystem::path& p);
+      directory_entry(const filesystem::path& p, error_code& ec);
+      ~directory_entry();
+
+      directory_entry& operator=(const directory_entry&) = default;
+      directory_entry& operator=(directory_entry&&) noexcept = default;
+
+      void assign(const filesystem::path& p);
+      void assign(const filesystem::path& p, error_code& ec);
+      void replace_filename(const filesystem::path& p);
+      void replace_filename(const filesystem::path& p, error_code& ec);
+      void refresh();
+      void refresh(error_code& ec) noexcept;
+
+      const filesystem::path& path() const noexcept;
+      operator const filesystem::path&() const noexcept;
+      bool exists() const;
+      bool exists(error_code& ec) const noexcept;
+      bool is_block_file() const;
+      bool is_block_file(error_code& ec) const noexcept;
+      bool is_character_file() const;
+      bool is_character_file(error_code& ec) const noexcept;
+      bool is_directory() const;
+      bool is_directory(error_code& ec) const noexcept;
+      bool is_fifo() const;
+      bool is_fifo(error_code& ec) const noexcept;
+      bool is_other() const;
+      bool is_other(error_code& ec) const noexcept;
+      bool is_regular_file() const;
+      bool is_regular_file(error_code& ec) const noexcept;
+      bool is_socket() const;
+      bool is_socket(error_code& ec) const noexcept;
+      bool is_symlink() const;
+      bool is_symlink(error_code& ec) const noexcept;
+      uintmax_t file_size() const;
+      uintmax_t file_size(error_code& ec) const noexcept;
+      uintmax_t hard_link_count() const;
+      uintmax_t hard_link_count(error_code& ec) const noexcept;
+      file_time_type last_write_time() const;
+      file_time_type last_write_time(error_code& ec) const noexcept;
+      file_status status() const;
+      file_status status(error_code& ec) const noexcept;
+      file_status symlink_status() const;
+      file_status symlink_status(error_code& ec) const noexcept;
+
+      bool operator==(const directory_entry& rhs) const noexcept;
+      bool operator!=(const directory_entry& rhs) const noexcept;             // removed  in C++20
+      bool operator< (const directory_entry& rhs) const noexcept;             // removed  in C++20
+      bool operator<=(const directory_entry& rhs) const noexcept;             // removed  in C++20
+      bool operator> (const directory_entry& rhs) const noexcept;             // removed  in C++20
+      bool operator>=(const directory_entry& rhs) const noexcept;             // removed  in C++20
+      strong_ordering operator<=>(const directory_entry& rhs) const noexcept; // since C++20
+
+      template<class charT, class traits>
+        friend basic_ostream<charT, traits>&
+          operator<<(basic_ostream<charT, traits>& os, const directory_entry& d);
+
+    private:
+      filesystem::path pathobject;        // exposition only
+      friend class directory_iterator;    // exposition only
+    };
 
     class directory_iterator;