// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_CODING_H_
#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_CODING_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "content/browser/indexed_db/scopes/scope_lock_range.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"

namespace content {

namespace indexed_db {
// 0 - Initial version.
// 1 - Adds UserIntVersion to DatabaseMetaData.
// 2 - Adds DataVersion to to global metadata.
// 3 - Adds metadata needed for blob support.
const constexpr int64_t kLatestKnownSchemaVersion = 3;
}  // namespace indexed_db

CONTENT_EXPORT extern const unsigned char kMinimumIndexId;

CONTENT_EXPORT std::string MaxIDBKey();
CONTENT_EXPORT std::string MinIDBKey();

// DatabaseId, BlobKey
typedef std::pair<int64_t, int64_t> BlobJournalEntryType;
typedef std::vector<BlobJournalEntryType> BlobJournalType;

CONTENT_EXPORT void EncodeByte(unsigned char value, std::string* into);
CONTENT_EXPORT void EncodeBool(bool value, std::string* into);

// Unlike EncodeVarInt, this is a 'dumb' implementation of a variable int
// encoder. It writes, little-endian', until there are no more '1' bits in the
// number. The Decoder must know how to calculate the size of the encoded int,
// typically by having this reside at the end of the value or key.
CONTENT_EXPORT void EncodeInt(int64_t value, std::string* into);
CONTENT_EXPORT void EncodeVarInt(int64_t value, std::string* into);
CONTENT_EXPORT void EncodeString(const base::string16& value,
                                 std::string* into);
CONTENT_EXPORT void EncodeStringWithLength(const base::string16& value,
                                           std::string* into);
CONTENT_EXPORT void EncodeBinary(const std::string& value, std::string* into);
CONTENT_EXPORT void EncodeDouble(double value, std::string* into);
CONTENT_EXPORT void EncodeIDBKey(const blink::IndexedDBKey& value,
                                 std::string* into);
CONTENT_EXPORT void EncodeIDBKeyPath(const blink::IndexedDBKeyPath& value,
                                     std::string* into);
CONTENT_EXPORT void EncodeBlobJournal(const BlobJournalType& journal,
                                      std::string* into);

CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeByte(base::StringPiece* slice,
                                                  unsigned char* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBool(base::StringPiece* slice,
                                                  bool* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeInt(base::StringPiece* slice,
                                                 int64_t* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeVarInt(base::StringPiece* slice,
                                                    int64_t* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeString(base::StringPiece* slice,
                                                    base::string16* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeStringWithLength(
    base::StringPiece* slice,
    base::string16* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBinary(base::StringPiece* slice,
                                                    std::string* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeDouble(base::StringPiece* slice,
                                                    double* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeIDBKey(
    base::StringPiece* slice,
    std::unique_ptr<blink::IndexedDBKey>* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeIDBKeyPath(
    base::StringPiece* slice,
    blink::IndexedDBKeyPath* value);
CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBlobJournal(
    base::StringPiece* slice,
    BlobJournalType* journal);

CONTENT_EXPORT int CompareEncodedStringsWithLength(base::StringPiece* slice1,
                                                   base::StringPiece* slice2,
                                                   bool* ok);

CONTENT_EXPORT WARN_UNUSED_RESULT bool ExtractEncodedIDBKey(
    base::StringPiece* slice,
    std::string* result);

CONTENT_EXPORT int CompareEncodedIDBKeys(base::StringPiece* slice1,
                                         base::StringPiece* slice2,
                                         bool* ok);

CONTENT_EXPORT int Compare(const base::StringPiece& a,
                           const base::StringPiece& b,
                           bool index_keys);

CONTENT_EXPORT int CompareKeys(const base::StringPiece& a,
                               const base::StringPiece& b);

CONTENT_EXPORT int CompareIndexKeys(const base::StringPiece& a,
                                    const base::StringPiece& b);

const constexpr int kDatabaseRangeLockLevel = 0;
const constexpr int kObjectStoreRangeLockLevel = 1;
const constexpr int kIndexedDBLockLevelCount = 2;

CONTENT_EXPORT ScopeLockRange GetDatabaseLockRange(int64_t database_id);
CONTENT_EXPORT ScopeLockRange GetObjectStoreLockRange(int64_t database_id,
                                                      int64_t object_store_id);

// TODO(dmurph): Modify all decoding methods to return something more sensible,
// as it is not obvious that they modify the input slice to remove the decoded
// bit. https://crbug.com/922225
class KeyPrefix {
 public:
  // These are serialized to disk; any new items must be appended, and none can
  // be deleted.
  enum Type {
    GLOBAL_METADATA = 0,
    DATABASE_METADATA = 1,
    OBJECT_STORE_DATA = 2,
    EXISTS_ENTRY = 3,
    INDEX_DATA = 4,
    INVALID_TYPE = 5,
    BLOB_ENTRY = 6
  };

  static const size_t kMaxDatabaseIdSizeBits = 3;
  static const size_t kMaxObjectStoreIdSizeBits = 3;
  static const size_t kMaxIndexIdSizeBits = 2;

  static const size_t kMaxDatabaseIdSizeBytes =
      1ULL << kMaxDatabaseIdSizeBits;  // 8
  static const size_t kMaxObjectStoreIdSizeBytes =
      1ULL << kMaxObjectStoreIdSizeBits;                                   // 8
  static const size_t kMaxIndexIdSizeBytes = 1ULL << kMaxIndexIdSizeBits;  // 4

  static const size_t kMaxDatabaseIdBits =
      kMaxDatabaseIdSizeBytes * 8 - 1;  // 63
  static const size_t kMaxObjectStoreIdBits =
      kMaxObjectStoreIdSizeBytes * 8 - 1;                              // 63
  static const size_t kMaxIndexIdBits = kMaxIndexIdSizeBytes * 8 - 1;  // 31

  static const int64_t kMaxDatabaseId =
      (1ULL << kMaxDatabaseIdBits) - 1;  // max signed int64_t
  static const int64_t kMaxObjectStoreId =
      (1ULL << kMaxObjectStoreIdBits) - 1;  // max signed int64_t
  static const int64_t kMaxIndexId =
      (1ULL << kMaxIndexIdBits) - 1;  // max signed int32_t

  static const int64_t kInvalidId = -1;

  KeyPrefix();
  explicit KeyPrefix(int64_t database_id);
  KeyPrefix(int64_t database_id, int64_t object_store_id);
  KeyPrefix(int64_t database_id, int64_t object_store_id, int64_t index_id);
  static KeyPrefix CreateWithSpecialIndex(int64_t database_id,
                                          int64_t object_store_id,
                                          int64_t index_id);

  static bool Decode(base::StringPiece* slice, KeyPrefix* result);
  std::string Encode() const;
  static std::string EncodeEmpty();
  int Compare(const KeyPrefix& other) const;

  CONTENT_EXPORT static bool IsValidDatabaseId(int64_t database_id);
  static bool IsValidObjectStoreId(int64_t index_id);
  static bool IsValidIndexId(int64_t index_id);
  static bool ValidIds(int64_t database_id,
                       int64_t object_store_id,
                       int64_t index_id) {
    return IsValidDatabaseId(database_id) &&
           IsValidObjectStoreId(object_store_id) && IsValidIndexId(index_id);
  }
  static bool ValidIds(int64_t database_id, int64_t object_store_id) {
    return IsValidDatabaseId(database_id) &&
           IsValidObjectStoreId(object_store_id);
  }

  Type type() const;

  int64_t database_id_;
  int64_t object_store_id_;
  int64_t index_id_;

 private:
  // Special constructor for CreateWithSpecialIndex()
  KeyPrefix(enum Type,
            int64_t database_id,
            int64_t object_store_id,
            int64_t index_id);

  static std::string EncodeInternal(int64_t database_id,
                                    int64_t object_store_id,
                                    int64_t index_id);
};

class SchemaVersionKey {
 public:
  CONTENT_EXPORT static std::string Encode();
};

class MaxDatabaseIdKey {
 public:
  CONTENT_EXPORT static std::string Encode();
};

class DataVersionKey {
 public:
  CONTENT_EXPORT static std::string Encode();
};

class BlobJournalKey {
 public:
  static std::string Encode();
};

class LiveBlobJournalKey {
 public:
  static std::string Encode();
};

class EarliestSweepKey {
 public:
  static std::string Encode();
};

class ScopesPrefix {
 public:
  CONTENT_EXPORT static std::vector<uint8_t> Encode();
};

class DatabaseFreeListKey {
 public:
  DatabaseFreeListKey();
  static bool Decode(base::StringPiece* slice, DatabaseFreeListKey* result);
  CONTENT_EXPORT static std::string Encode(int64_t database_id);
  static CONTENT_EXPORT std::string EncodeMaxKey();
  int64_t DatabaseId() const;
  int Compare(const DatabaseFreeListKey& other) const;

 private:
  int64_t database_id_;
};

class DatabaseNameKey {
 public:
  static bool Decode(base::StringPiece* slice, DatabaseNameKey* result);
  CONTENT_EXPORT static std::string Encode(const std::string& origin_identifier,
                                           const base::string16& database_name);
  static std::string EncodeMinKeyForOrigin(
      const std::string& origin_identifier);
  static std::string EncodeStopKeyForOrigin(
      const std::string& origin_identifier);
  base::string16 origin() const { return origin_; }
  base::string16 database_name() const { return database_name_; }
  int Compare(const DatabaseNameKey& other);

 private:
  base::string16 origin_;  // TODO(jsbell): Store encoded strings, or just
                           // pointers.
  base::string16 database_name_;
};

class DatabaseMetaDataKey {
 public:
  enum MetaDataType {
    ORIGIN_NAME = 0,
    DATABASE_NAME = 1,
    USER_STRING_VERSION = 2,  // Obsolete
    MAX_OBJECT_STORE_ID = 3,
    USER_VERSION = 4,
    BLOB_KEY_GENERATOR_CURRENT_NUMBER = 5,
    MAX_SIMPLE_METADATA_TYPE = 6
  };

  CONTENT_EXPORT static const int64_t kAllBlobsKey;
  static const int64_t kBlobKeyGeneratorInitialNumber;
  // All keys <= 0 are invalid.  This one's just a convenient example.
  static const int64_t kInvalidBlobKey;

  static bool IsValidBlobKey(int64_t blob_key);
  CONTENT_EXPORT static std::string Encode(int64_t database_id,
                                           MetaDataType type);
};

class ObjectStoreMetaDataKey {
 public:
  enum MetaDataType {
    NAME = 0,
    KEY_PATH = 1,
    AUTO_INCREMENT = 2,
    EVICTABLE = 3,
    LAST_VERSION = 4,
    MAX_INDEX_ID = 5,
    HAS_KEY_PATH = 6,
    KEY_GENERATOR_CURRENT_NUMBER = 7
  };

  // From the IndexedDB specification.
  static const int64_t kKeyGeneratorInitialNumber;

  ObjectStoreMetaDataKey();
  static bool Decode(base::StringPiece* slice, ObjectStoreMetaDataKey* result);
  CONTENT_EXPORT static std::string Encode(int64_t database_id,
                                           int64_t object_store_id,
                                           unsigned char meta_data_type);
  CONTENT_EXPORT static std::string EncodeMaxKey(int64_t database_id);
  CONTENT_EXPORT static std::string EncodeMaxKey(int64_t database_id,
                                                 int64_t object_store_id);
  int64_t ObjectStoreId() const;
  unsigned char MetaDataType() const;
  int Compare(const ObjectStoreMetaDataKey& other);

 private:
  int64_t object_store_id_;
  unsigned char meta_data_type_;
};

class IndexMetaDataKey {
 public:
  enum MetaDataType {
    NAME = 0,
    UNIQUE = 1,
    KEY_PATH = 2,
    MULTI_ENTRY = 3
  };

  IndexMetaDataKey();
  static bool Decode(base::StringPiece* slice, IndexMetaDataKey* result);
  CONTENT_EXPORT static std::string Encode(int64_t database_id,
                                           int64_t object_store_id,
                                           int64_t index_id,
                                           unsigned char meta_data_type);
  CONTENT_EXPORT static std::string EncodeMaxKey(int64_t database_id,
                                                 int64_t object_store_id);
  CONTENT_EXPORT static std::string EncodeMaxKey(int64_t database_id,
                                                 int64_t object_store_id,
                                                 int64_t index_id);
  int Compare(const IndexMetaDataKey& other);
  int64_t IndexId() const;
  unsigned char meta_data_type() const { return meta_data_type_; }

 private:
  int64_t object_store_id_;
  int64_t index_id_;
  unsigned char meta_data_type_;
};

class ObjectStoreFreeListKey {
 public:
  ObjectStoreFreeListKey();
  static bool Decode(base::StringPiece* slice, ObjectStoreFreeListKey* result);
  CONTENT_EXPORT static std::string Encode(int64_t database_id,
                                           int64_t object_store_id);
  CONTENT_EXPORT static std::string EncodeMaxKey(int64_t database_id);
  int64_t ObjectStoreId() const;
  int Compare(const ObjectStoreFreeListKey& other);

 private:
  int64_t object_store_id_;
};

class IndexFreeListKey {
 public:
  IndexFreeListKey();
  static bool Decode(base::StringPiece* slice, IndexFreeListKey* result);
  CONTENT_EXPORT static std::string Encode(int64_t database_id,
                                           int64_t object_store_id,
                                           int64_t index_id);
  CONTENT_EXPORT static std::string EncodeMaxKey(int64_t database_id,
                                                 int64_t object_store_id);
  int Compare(const IndexFreeListKey& other);
  int64_t ObjectStoreId() const;
  int64_t IndexId() const;

 private:
  int64_t object_store_id_;
  int64_t index_id_;
};

class ObjectStoreNamesKey {
 public:
  // TODO(jsbell): We never use this to look up object store ids,
  // because a mapping is kept in the IndexedDBDatabase. Can the
  // mapping become unreliable?  Can we remove this?
  static bool Decode(base::StringPiece* slice, ObjectStoreNamesKey* result);
  CONTENT_EXPORT static std::string Encode(
      int64_t database_id,
      const base::string16& object_store_name);
  int Compare(const ObjectStoreNamesKey& other);
  base::string16 object_store_name() const { return object_store_name_; }

 private:
  // TODO(jsbell): Store the encoded string, or just pointers to it.
  base::string16 object_store_name_;
};

class IndexNamesKey {
 public:
  IndexNamesKey();
  // TODO(jsbell): We never use this to look up index ids, because a mapping
  // is kept at a higher level.
  static bool Decode(base::StringPiece* slice, IndexNamesKey* result);
  CONTENT_EXPORT static std::string Encode(int64_t database_id,
                                           int64_t object_store_id,
                                           const base::string16& index_name);
  int Compare(const IndexNamesKey& other);
  base::string16 index_name() const { return index_name_; }

 private:
  int64_t object_store_id_;
  base::string16 index_name_;
};

class ObjectStoreDataKey {
 public:
  static const int64_t kSpecialIndexNumber;

  ObjectStoreDataKey();
  ~ObjectStoreDataKey();

  static bool Decode(base::StringPiece* slice, ObjectStoreDataKey* result);
  CONTENT_EXPORT static std::string Encode(int64_t database_id,
                                           int64_t object_store_id,
                                           const std::string encoded_user_key);
  static std::string Encode(int64_t database_id,
                            int64_t object_store_id,
                            const blink::IndexedDBKey& user_key);
  std::unique_ptr<blink::IndexedDBKey> user_key() const;

 private:
  std::string encoded_user_key_;
};

class ExistsEntryKey {
 public:
  ExistsEntryKey();
  ~ExistsEntryKey();

  static bool Decode(base::StringPiece* slice, ExistsEntryKey* result);
  CONTENT_EXPORT static std::string Encode(int64_t database_id,
                                           int64_t object_store_id,
                                           const std::string& encoded_key);
  static std::string Encode(int64_t database_id,
                            int64_t object_store_id,
                            const blink::IndexedDBKey& user_key);
  std::unique_ptr<blink::IndexedDBKey> user_key() const;

 private:
  static const int64_t kSpecialIndexNumber;

  std::string encoded_user_key_;
  DISALLOW_COPY_AND_ASSIGN(ExistsEntryKey);
};

class BlobEntryKey {
 public:
  BlobEntryKey() : database_id_(0), object_store_id_(0) {}
  static bool Decode(base::StringPiece* slice, BlobEntryKey* result);
  static bool FromObjectStoreDataKey(base::StringPiece* slice,
                                     BlobEntryKey* result);
  static std::string ReencodeToObjectStoreDataKey(base::StringPiece* slice);
  static std::string EncodeMinKeyForObjectStore(int64_t database_id,
                                                int64_t object_store_id);
  static std::string EncodeStopKeyForObjectStore(int64_t database_id,
                                                 int64_t object_store_id);
  static std::string Encode(int64_t database_id,
                            int64_t object_store_id,
                            const blink::IndexedDBKey& user_key);
  std::string Encode() const;
  int64_t database_id() const { return database_id_; }
  int64_t object_store_id() const { return object_store_id_; }

 private:
  static const int64_t kSpecialIndexNumber;

  static std::string Encode(int64_t database_id,
                            int64_t object_store_id,
                            const std::string& encoded_user_key);
  int64_t database_id_;
  int64_t object_store_id_;
  // This is the user's ObjectStoreDataKey, not the BlobEntryKey itself.
  std::string encoded_user_key_;
};

class IndexDataKey {
 public:
  CONTENT_EXPORT IndexDataKey();
  CONTENT_EXPORT IndexDataKey(IndexDataKey&& other);
  CONTENT_EXPORT ~IndexDataKey();
  CONTENT_EXPORT static bool Decode(base::StringPiece* slice,
                                    IndexDataKey* result);
  CONTENT_EXPORT static std::string Encode(
      int64_t database_id,
      int64_t object_store_id,
      int64_t index_id,
      const std::string& encoded_user_key,
      const std::string& encoded_primary_key,
      int64_t sequence_number);
  static std::string Encode(int64_t database_id,
                            int64_t object_store_id,
                            int64_t index_id,
                            const blink::IndexedDBKey& user_key);
  CONTENT_EXPORT static std::string Encode(
      int64_t database_id,
      int64_t object_store_id,
      int64_t index_id,
      const blink::IndexedDBKey& user_key,
      const blink::IndexedDBKey& user_primary_key);
  CONTENT_EXPORT static std::string EncodeMinKey(int64_t database_id,
                                                 int64_t object_store_id,
                                                 int64_t index_id);

  // An index's keys are guaranteed to fall in [EncodeMinKey(), EncodeMaxKey()]
  CONTENT_EXPORT static std::string EncodeMaxKey(int64_t database_id,
                                                 int64_t object_store_id,
                                                 int64_t index_id);
  int64_t DatabaseId() const;
  int64_t ObjectStoreId() const;
  int64_t IndexId() const;
  std::unique_ptr<blink::IndexedDBKey> user_key() const;
  std::unique_ptr<blink::IndexedDBKey> primary_key() const;

  CONTENT_EXPORT std::string Encode() const;

 private:
  int64_t database_id_;
  int64_t object_store_id_;
  int64_t index_id_;
  std::string encoded_user_key_;
  std::string encoded_primary_key_;
  int64_t sequence_number_;

  DISALLOW_COPY_AND_ASSIGN(IndexDataKey);
};

}  // namespace content

#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_CODING_H_
