| /* |
| * |
| * Copyright (c) 2022 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #pragma once |
| |
| #include <lib/core/CHIPPersistentStorageDelegate.h> |
| #include <lib/core/TLV.h> |
| #include <lib/support/DefaultStorageKeyAllocator.h> |
| #include <lib/support/Span.h> |
| |
| namespace chip { |
| |
| /// @brief Data that can be persisted via PersistentStorageDelegate in TLV format. |
| struct DataAccessor |
| { |
| virtual ~DataAccessor() = default; |
| virtual CHIP_ERROR UpdateKey(StorageKeyName & key) const = 0; |
| virtual CHIP_ERROR Serialize(TLV::TLVWriter & writer) const = 0; |
| virtual CHIP_ERROR Deserialize(TLV::TLVReader & reader) = 0; |
| virtual void Clear() = 0; |
| |
| /// Non-virtual helper methods /// |
| |
| CHIP_ERROR Save(PersistentStorageDelegate * storage, const MutableByteSpan & buffer) const |
| { |
| VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); |
| |
| StorageKeyName key = StorageKeyName::Uninitialized(); |
| ReturnErrorOnFailure(this->UpdateKey(key)); |
| |
| // Serialize the data |
| TLV::TLVWriter writer; |
| writer.Init(buffer); |
| ReturnErrorOnFailure(this->Serialize(writer)); |
| |
| // Save serialized data |
| return storage->SyncSetKeyValue(key.KeyName(), buffer.data(), static_cast<uint16_t>(writer.GetLengthWritten())); |
| } |
| |
| CHIP_ERROR Load(PersistentStorageDelegate * storage, const MutableByteSpan & buffer) |
| { |
| VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); |
| |
| StorageKeyName key = StorageKeyName::Uninitialized(); |
| ReturnErrorOnFailure(this->UpdateKey(key)); |
| |
| // Set data to defaults |
| this->Clear(); |
| |
| // Load the serialized data |
| uint16_t size = (buffer.size() > UINT16_MAX) ? UINT16_MAX : static_cast<uint16_t>(buffer.size()); |
| CHIP_ERROR err = storage->SyncGetKeyValue(key.KeyName(), buffer.data(), size); |
| VerifyOrReturnError(CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND != err, CHIP_ERROR_NOT_FOUND); |
| ReturnErrorOnFailure(err); |
| |
| // Decode serialized data |
| TLV::TLVReader reader; |
| reader.Init(buffer.data(), size); |
| return this->Deserialize(reader); |
| } |
| |
| CHIP_ERROR Delete(PersistentStorageDelegate * storage) const |
| { |
| VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); |
| |
| StorageKeyName key = StorageKeyName::Uninitialized(); |
| ReturnErrorOnFailure(this->UpdateKey(key)); |
| |
| return storage->SyncDeleteKeyValue(key.KeyName()); |
| } |
| }; |
| |
| /// @brief A buffer to be used when loading or serializing persistent data |
| /// @tparam kMaxSerializedSize size of the buffer necessary to retrieve an entry from the storage. |
| /// |
| /// Note: Generic APIs that utilize a persistence buffer should prefer taking |
| /// a MutableByteSpan, to avoid unnecessarily templating on the buffer size. |
| template <size_t kMaxSerializedSize> |
| struct PersistenceBuffer |
| { |
| uint8_t mBuffer[kMaxSerializedSize]; |
| |
| // Returns a MutableByteSpan representing this buffer. |
| MutableByteSpan BufferSpan() { return MutableByteSpan(mBuffer); } |
| }; |
| |
| /// @brief A DataAccessor with a built-in buffer. |
| /// @tparam kMaxSerializedSize inherited from PersistenceBuffer |
| /// |
| /// Note: Unlike `PersistentData` (deprecated), this class does not make the Load/Save/Delete |
| /// methods virtual. PersistableData objects are not intended to be used polymorphically. |
| /// It also does not store a PersistentStorageDelegate pointer internally. |
| template <size_t kMaxSerializedSize> |
| class PersistableData : public DataAccessor, protected PersistenceBuffer<kMaxSerializedSize> |
| { |
| public: |
| CHIP_ERROR Save(PersistentStorageDelegate * storage) { return DataAccessor::Save(storage, this->BufferSpan()); } |
| CHIP_ERROR Load(PersistentStorageDelegate * storage) { return DataAccessor::Load(storage, this->BufferSpan()); } |
| }; |
| |
| ///// Deprecated types retained for backward compatibility //////////////////// |
| |
| // Deprecated: use PersistenceBuffer and DataAccessor separately |
| template <size_t kMaxSerializedSize> |
| struct PersistentStore : public PersistenceBuffer<kMaxSerializedSize> |
| { |
| virtual ~PersistentStore() = default; |
| |
| CHIP_ERROR Save(const DataAccessor & persistent, PersistentStorageDelegate * storage) |
| { |
| return persistent.Save(storage, this->BufferSpan()); |
| } |
| |
| CHIP_ERROR Load(DataAccessor & persistent, PersistentStorageDelegate * storage) |
| { |
| return persistent.Load(storage, this->BufferSpan()); |
| } |
| |
| CHIP_ERROR Delete(DataAccessor & persistent, PersistentStorageDelegate * storage) { return persistent.Delete(storage); } |
| }; |
| |
| // Deprecated: use PersistableData instead |
| template <size_t kMaxSerializedSize> |
| struct PersistentData : PersistentStore<kMaxSerializedSize>, DataAccessor |
| { |
| using SizedStore = PersistentStore<kMaxSerializedSize>; |
| |
| PersistentData(PersistentStorageDelegate * storage = nullptr) : mStorage(storage) {} |
| virtual ~PersistentData() = default; |
| |
| virtual CHIP_ERROR Save() { return this->Save(this->mStorage); } |
| |
| virtual CHIP_ERROR Save(PersistentStorageDelegate * storage) { return SizedStore::Save(*this, storage); } |
| |
| virtual CHIP_ERROR Load() { return this->Load(this->mStorage); } |
| |
| virtual CHIP_ERROR Load(PersistentStorageDelegate * storage) { return SizedStore::Load(*this, storage); } |
| |
| virtual CHIP_ERROR Delete(PersistentStorageDelegate * storage) { return SizedStore::Delete(*this, storage); } |
| |
| PersistentStorageDelegate * mStorage = nullptr; |
| }; |
| |
| } // namespace chip |