xref: /aosp_15_r20/external/pigweed/pw_kvs/public/pw_kvs/checksum.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 <cstddef>
17 
18 #include "pw_kvs/alignment.h"
19 #include "pw_span/span.h"
20 #include "pw_status/status.h"
21 
22 namespace pw {
23 namespace kvs {
24 
25 class ChecksumAlgorithm {
26  public:
27   // Resets the checksum to its initial state.
28   virtual void Reset() = 0;
29 
30   // Updates the checksum with the provided data.
31   virtual void Update(span<const std::byte> data) = 0;
32 
33   // Updates the checksum from a pointer and size.
Update(const void * data,size_t size_bytes)34   void Update(const void* data, size_t size_bytes) {
35     return Update(
36         span<const std::byte>(static_cast<const std::byte*>(data), size_bytes));
37   }
38 
39   // Returns the final result of the checksum. Update() can no longer be called
40   // after this. The returned span is valid until a call to Reset().
41   //
42   // Finish MUST be called before calling Verify.
Finish()43   span<const std::byte> Finish() {
44     Finalize();  // Implemented by derived classes, if required.
45     return state();
46   }
47 
48   // Returns the size of the checksum state.
size_bytes()49   constexpr size_t size_bytes() const { return state_.size(); }
50 
51   // Compares a calculated checksum to this checksum's state. The checksum must
52   // be at least as large as size_bytes(). If it is larger, bytes beyond
53   // size_bytes() are ignored.
54   //
55   // Finish MUST be called before calling Verify.
56   Status Verify(span<const std::byte> checksum) const;
57 
58  protected:
59   // A derived class provides a span of its state buffer.
ChecksumAlgorithm(span<const std::byte> state)60   constexpr ChecksumAlgorithm(span<const std::byte> state) : state_(state) {}
61 
62   // Protected destructor prevents deleting ChecksumAlgorithms from the base
63   // class, so that it is safe to have a non-virtual destructor.
64   ~ChecksumAlgorithm() = default;
65 
66   // Returns the current checksum state.
state()67   constexpr span<const std::byte> state() const { return state_; }
68 
69  private:
70   // Checksums that require finalizing operations may override this method.
Finalize()71   virtual void Finalize() {}
72 
73   span<const std::byte> state_;
74 };
75 
76 // A checksum algorithm for which Verify always passes. This can be used to
77 // disable checksum verification for a particular entry format.
78 class IgnoreChecksum final : public ChecksumAlgorithm {
79  public:
IgnoreChecksum()80   constexpr IgnoreChecksum() : ChecksumAlgorithm({}) {}
81 
Reset()82   void Reset() override {}
Update(span<const std::byte>)83   void Update(span<const std::byte>) override {}
84 };
85 
86 // Calculates a checksum in kAlignmentBytes chunks. Checksum classes can inherit
87 // from this and implement UpdateAligned and FinalizeAligned instead of Update
88 // and Finalize.
89 template <size_t kAlignmentBytes, size_t kBufferSize = kAlignmentBytes>
90 class AlignedChecksum : public ChecksumAlgorithm {
91  public:
Update(span<const std::byte> data)92   void Update(span<const std::byte> data) final {
93     writer_.Write(data)
94         .IgnoreError();  // TODO: b/242598609 - Handle Status properly
95   }
96 
97  protected:
AlignedChecksum(span<const std::byte> state)98   constexpr AlignedChecksum(span<const std::byte> state)
99       : ChecksumAlgorithm(state),
100         output_(*this),
101         writer_(kAlignmentBytes, output_) {}
102 
103   ~AlignedChecksum() = default;
104 
105  private:
106   static_assert(kBufferSize >= kAlignmentBytes);
107 
Finalize()108   void Finalize() final {
109     writer_.Flush()
110         .IgnoreError();  // TODO: b/242598609 - Handle Status properly
111     FinalizeAligned();
112   }
113 
114   virtual void UpdateAligned(span<const std::byte> data) = 0;
115 
116   virtual void FinalizeAligned() = 0;
117 
118   class CallUpdateAligned final : public Output {
119    public:
CallUpdateAligned(AlignedChecksum & object)120     constexpr CallUpdateAligned(AlignedChecksum& object) : object_(object) {}
121 
122    private:
DoWrite(span<const std::byte> data)123     StatusWithSize DoWrite(span<const std::byte> data) override {
124       object_.UpdateAligned(data);
125       return StatusWithSize(data.size());
126     }
127 
128     AlignedChecksum& object_;
129   };
130 
131   CallUpdateAligned output_;
132   AlignedWriterBuffer<kBufferSize> writer_;
133 };
134 
135 }  // namespace kvs
136 }  // namespace pw
137