// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_DISK_CACHE_SQL_CACHE_ENTRY_KEY_H_
#define NET_DISK_CACHE_SQL_CACHE_ENTRY_KEY_H_

#include <optional>
#include <string>
#include <string_view>

#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/types/strong_alias.h"
#include "net/base/net_export.h"
#include "net/disk_cache/sql/sql_backend_aliases.h"

namespace disk_cache {

// Represents the key for a cache entry in the SQL disk cache backend.
//
// This class is an immutable wrapper around the cache key string generated by
// HttpCache::GenerateCacheKeyForRequest(). To reduce memory consumption across
// internal maps, it stores data in a ref-counted struct
// (`base::RefCountedData`).
//
// When the `kRendererAccessibleHttpCache` feature is enabled, this class also
// extracts and stores the resource URL and its PersistentHash at construction.
// Calling `resource_url()` or `resource_url_hash()` requires that the feature
// `kRendererAccessibleHttpCache` is enabled (enforced via CHECK).
class NET_EXPORT_PRIVATE CacheEntryKey {
 public:
  using Hash = CacheEntryKeyHash;

  // A utility to compute the hash of a string, without needing to create a
  // CacheEntryKey object.
  static Hash HashFromString(const std::string_view str);

  explicit CacheEntryKey(std::string str = "");
  ~CacheEntryKey();

  CacheEntryKey(const CacheEntryKey& other);
  CacheEntryKey(CacheEntryKey&& other);
  CacheEntryKey& operator=(const CacheEntryKey& other);
  CacheEntryKey& operator=(CacheEntryKey&& other);

  bool operator<(const CacheEntryKey& other) const;
  bool operator==(const CacheEntryKey& other) const;

  const std::string& string() const;
  Hash hash() const;

  // Requires the `kRendererAccessibleHttpCache` feature to be enabled.
  std::string_view resource_url() const;
  // Requires the `kRendererAccessibleHttpCache` feature to be enabled.
  SqlSharedCacheUrlHash resource_url_hash() const;

 private:
  struct Data {
    explicit Data(std::string key_str);

    const std::string key;
    const Hash hash;
    // Points to a substring within `key`. Must be declared after `key`.
    const std::string_view resource_url;
    const SqlSharedCacheUrlHash resource_url_hash;
  };

  scoped_refptr<const base::RefCountedData<Data>> data_;
};

}  // namespace disk_cache

namespace std {

// Implement hashing of CacheEntryKey, so it can be used as key in STL
// containers.
template <>
struct hash<disk_cache::CacheEntryKey> {
  std::size_t operator()(const disk_cache::CacheEntryKey& k) const {
    // Narrowing conversion happens when sizeof(std::size_t) is less than 64.
    return k.hash().value();
  }
};

}  // namespace std

#endif  // NET_DISK_CACHE_SQL_CACHE_ENTRY_KEY_H_
