xref: /aosp_15_r20/external/pigweed/pw_kvs/public/pw_kvs/format.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <cstdint>
17 
18 #include "pw_kvs/checksum.h"
19 #include "pw_span/span.h"
20 
21 namespace pw {
22 namespace kvs {
23 
24 // The EntryFormat defines properties of KVS entries that use a particular magic
25 // number.
26 struct EntryFormat {
27   // Magic is a unique constant identifier for entries.
28   //
29   // Upon reading from an address in flash, the magic number facilitiates
30   // quickly differentiating between:
31   //
32   // - Reading erased data - typically 0xFF - from flash.
33   // - Reading corrupted data
34   // - Reading a valid entry
35   //
36   // When selecting a magic for your particular KVS, pick a random 32 bit
37   // integer rather than a human readable 4 bytes. This decreases the
38   // probability of a collision with a real string when scanning in the case of
39   // corruption. To generate such a number:
40   /*
41        $ python3 -c 'import random; print(hex(random.randint(0,2**32)))'
42        0xaf741757
43   */
44   uint32_t magic;
45 
46   // The checksum algorithm is used to calculate checksums for KVS entries. If
47   // it is null, no checksum is used.
48   ChecksumAlgorithm* checksum;
49 };
50 
51 namespace internal {
52 
53 // Disk format of the header used for each key-value entry.
54 struct EntryHeader {
55   // For KVS magic value always use a random 32 bit integer rather than a
56   // human readable 4 bytes. See pw_kvs/format.h::EntryFormat for more
57   // information.
58   uint32_t magic;
59 
60   // The checksum of the entire entry, including the header, key, value, and
61   // zero-value padding bytes. The checksum is calculated as if the checksum
62   // field value was zero.
63   uint32_t checksum;
64 
65   // Stores the alignment in 16-byte units, starting from 16. To calculate the
66   // number of bytes, add one to this number and multiply by 16.
67   uint8_t alignment_units;
68 
69   // The length of the key in bytes. The key is not null terminated.
70   //  6 bits, 0:5 - key length - maximum 64 characters
71   //  2 bits, 6:7 - reserved
72   uint8_t key_length_bytes;
73 
74   // Byte length of the value; maximum of 65534. The max uint16_t value (65535
75   // or 0xFFFF) is reserved to indicate this is a tombstone (deleted) entry.
76   uint16_t value_size_bytes;
77 
78   // The transaction ID for this key. Monotonically increasing.
79   uint32_t transaction_id;
80 };
81 
82 static_assert(sizeof(EntryHeader) == 16, "EntryHeader must not have padding");
83 
84 // This class wraps EntryFormat instances to support having multiple
85 // simultaneously supported formats.
86 class EntryFormats {
87  public:
EntryFormats(span<const EntryFormat> formats)88   explicit constexpr EntryFormats(span<const EntryFormat> formats)
89       : formats_(formats) {}
90 
EntryFormats(const EntryFormat & format)91   explicit constexpr EntryFormats(const EntryFormat& format)
92       : formats_(&format, 1) {}
93 
primary()94   const EntryFormat& primary() const { return formats_.front(); }
95 
KnownMagic(uint32_t magic)96   bool KnownMagic(uint32_t magic) const { return Find(magic) != nullptr; }
97 
98   const EntryFormat* Find(uint32_t magic) const;
99 
100  private:
101   const span<const EntryFormat> formats_;
102 };
103 
104 }  // namespace internal
105 }  // namespace kvs
106 }  // namespace pw
107