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 <array> 17 #include <cstddef> 18 #include <span> 19 20 #include "pw_assert/light.h" 21 #include "pw_bytes/span.h" 22 #include "pw_result/result.h" 23 #include "pw_status/status.h" 24 #include "pw_status/status_with_size.h" 25 26 namespace pw::stream { 27 28 // General-purpose writer interface. 29 class Writer { 30 public: 31 // There are no requirements around if or how a `Writer` should call Flush() 32 // at the time of object destruction. 33 virtual ~Writer() = default; 34 35 // Write data to this stream Writer. Data is 36 // not guaranteed to be fully written out to final resting place on Write 37 // return. 38 // 39 // If the writer is unable to fully accept the input data size it will abort 40 // the write and return RESOURCE_EXHAUSTED. 41 // 42 // If the writer has been exhausted and is and can no longer accept additional 43 // bytes it will return OUT_OF_RANGE. This is similar to EndOfFile. Write will 44 // only return OUT_OF_RANGE if ConservativeWriteLimit() is and will remain 45 // zero. A Write operation that is successful and also exhausts the writer 46 // returns OK, with all following calls returning OUT_OF_RANGE. When 47 // ConservativeWriteLimit() is greater than zero, a Write that is a number of 48 // bytes beyond what will exhaust the Write will abort and return 49 // RESOURCE_EXHAUSTED rather than OUT_OF_RANGE because the writer is still 50 // able to write bytes. 51 // 52 // Derived classes should NOT try to override the public Write methods. 53 // Instead, provide an implementation by overriding DoWrite(). 54 // 55 // Returns: 56 // 57 // OK - successful write/enqueue of data. 58 // FAILED_PRECONDITION - writer unable/not in state to accept data. 59 // RESOURCE_EXHAUSTED - unable to write all of requested data at this time. No 60 // data written. 61 // OUT_OF_RANGE - Writer has been exhausted, similar to EOF. No data written, 62 // no more will be written. Write(ConstByteSpan data)63 Status Write(ConstByteSpan data) { 64 PW_DASSERT(data.empty() || data.data() != nullptr); 65 return DoWrite(data); 66 } Write(const void * data,size_t size_bytes)67 Status Write(const void* data, size_t size_bytes) { 68 return Write(std::span(static_cast<const std::byte*>(data), size_bytes)); 69 } Write(const std::byte b)70 Status Write(const std::byte b) { return Write(&b, 1); } 71 72 // Probable (not guaranteed) minimum number of bytes at this time that can be 73 // written. This number is advisory and not guaranteed to write without a 74 // RESOURCE_EXHAUSTED or OUT_OF_RANGE. As Writer processes/handles enqueued of 75 // other contexts write data this number can go up or down for some Writers. 76 // Returns zero if, in the current state, Write() would not return 77 // OkStatus(). 78 // 79 // Returns std::numeric_limits<size_t>::max() if the implementation has no 80 // limits on write sizes. ConservativeWriteLimit()81 virtual size_t ConservativeWriteLimit() const { 82 return std::numeric_limits<size_t>::max(); 83 } 84 85 private: 86 virtual Status DoWrite(ConstByteSpan data) = 0; 87 }; 88 89 // General-purpose reader interface 90 class Reader { 91 public: 92 virtual ~Reader() = default; 93 94 // Read data from this stream Reader. If any number of bytes are read return 95 // OK with a span of the actual byte read. 96 // 97 // If the reader has been exhausted and is and can no longer read additional 98 // bytes it will return OUT_OF_RANGE. This is similar to EndOfFile. Read will 99 // only return OUT_OF_RANGE if ConservativeReadLimit() is and will remain 100 // zero. A Read operation that is successful and also exhausts the reader 101 // returns OK, with all following calls returning OUT_OF_RANGE. 102 // 103 // Derived classes should NOT try to override these public read methods. 104 // Instead, provide an implementation by overriding DoRead(). 105 // 106 // Returns: 107 // 108 // OK with span of bytes read - success, between 1 and dest.size_bytes() were 109 // read. 110 // FAILED_PRECONDITION - Reader unable/not in state to read data. 111 // RESOURCE_EXHAUSTED - unable to read any bytes at this time. No bytes read. 112 // Try again once bytes become available. 113 // OUT_OF_RANGE - Reader has been exhausted, similar to EOF. No bytes read, no 114 // more will be read. Read(ByteSpan dest)115 Result<ByteSpan> Read(ByteSpan dest) { 116 PW_DASSERT(dest.empty() || dest.data() != nullptr); 117 StatusWithSize result = DoRead(dest); 118 119 if (result.ok()) { 120 return dest.first(result.size()); 121 } else { 122 return result.status(); 123 } 124 } Read(void * dest,size_t size_bytes)125 Result<ByteSpan> Read(void* dest, size_t size_bytes) { 126 return Read(std::span(static_cast<std::byte*>(dest), size_bytes)); 127 } 128 129 // Probable (not guaranteed) minimum number of bytes at this time that can be 130 // read. This number is advisory and not guaranteed to read full number of 131 // requested bytes or without a RESOURCE_EXHAUSTED or OUT_OF_RANGE. As Reader 132 // processes/handles/receives enqueued data or other contexts read data this 133 // number can go up or down for some Readers. 134 // Returns zero if, in the current state, Read() would not return 135 // OkStatus(). 136 // 137 // Returns std::numeric_limits<size_t>::max() if the implementation imposes no 138 // limits on read sizes. ConservativeReadLimit()139 virtual size_t ConservativeReadLimit() const { 140 return std::numeric_limits<size_t>::max(); 141 } 142 143 private: 144 virtual StatusWithSize DoRead(ByteSpan dest) = 0; 145 }; 146 147 } // namespace pw::stream 148