• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2025 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 
15 #pragma once
16 
17 #include "pw_bytes/span.h"
18 #include "pw_multibuf/allocator.h"
19 #include "pw_multibuf/multibuf.h"
20 #include "pw_result/result.h"
21 #include "pw_span/cast.h"
22 #include "pw_span/span.h"
23 
24 namespace pw::bluetooth::proxy {
25 
26 /// Wraps a fixed-size contiguous MultiBuf and allows for easily writing
27 /// sequential data into it.
28 ///
29 /// * A MultiBufWriter is created using Create().
30 /// * Data can be written with Write() until IsComplete() returns true.
31 /// * The data can be viewed with U8Span() or TakeMultiBuf().
32 class MultiBufWriter {
33  public:
34   /// Creates a MultiBufWriter wrapping a fixed-size, contiguous MultiBuf.
35   static pw::Result<MultiBufWriter> Create(
36       multibuf::MultiBufAllocator& multibuf_allocator, size_t size);
37 
38   // MultiBufWriter is movable but not copyable.
39   MultiBufWriter(const MultiBufWriter&) = delete;
40   MultiBufWriter& operator=(const MultiBufWriter&) = delete;
41   MultiBufWriter(MultiBufWriter&&) = default;
42   MultiBufWriter& operator=(MultiBufWriter&&) = default;
43 
44   /// Gets a span of the previously-written data.
45   ///
46   /// After TakeMultiBuf(), this returns an empty span.
U8Span()47   pw::span<uint8_t> U8Span() {
48     // ContiguousSpan() cannot fail because Create() uses AllocateContiguous().
49     return pw::span_cast<uint8_t>(*buf_.ContiguousSpan()).first(write_offset_);
50   }
51 
52   /// Returns true when the MultiBuf is full; i.e., when the total number of
53   /// bytes written equals the size passed to Create(). Always returns true
54   /// after TakeMultiBuf() is called.
IsComplete()55   bool IsComplete() const { return remain() == 0; }
56 
57   /// Consumes the underlying MultiBuf.
58   ///
59   /// After this method is called, this object is reset to an empty state:
60   /// No data can be written, and all data accesors will return an empty
61   /// result. IsComplete() will return true.
TakeMultiBuf()62   multibuf::MultiBuf&& TakeMultiBuf() {
63     write_offset_ = 0;
64 
65     // A moved-from MultiBuf is equivalent to a default, empty MultiBuf.
66     return std::move(buf_);
67   }
68 
69   /// Writes data into the MultiBuf at the next unwritten location.
70   Status Write(pw::ConstByteSpan data);
71 
Write(pw::span<const uint8_t> data)72   Status Write(pw::span<const uint8_t> data) {
73     return Write(pw::as_bytes(data));
74   }
75 
76  private:
MultiBufWriter(multibuf::MultiBuf && buf)77   MultiBufWriter(multibuf::MultiBuf&& buf) : buf_(std::move(buf)) {}
78 
79   /// Returns the number of bytes remaining to be written before IsComplete()
80   /// returns true.
remain()81   size_t remain() const { return buf_.size() - write_offset_; }
82 
83   multibuf::MultiBuf buf_;
84   size_t write_offset_ = 0;
85 };
86 
87 }  // namespace pw::bluetooth::proxy
88