1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://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,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef STREAM_BUFFER_H
17#define STREAM_BUFFER_H
18
19#include <string>
20#include <vector>
21
22#include "nocopyable.h"
23#include "securec.h"
24
25#include "proto.h"
26#include "sensor_errors.h"
27
28#ifdef OHOS_BUILD_ENABLE_RUST
29#include "rust_binding.h"
30#endif // OHOS_BUILD_ENABLE_RUST
31
32#undef LOG_TAG
33#define LOG_TAG "StreamBuffer"
34
35namespace OHOS {
36namespace Sensors {
37class StreamBuffer {
38public:
39    StreamBuffer() = default;
40    explicit StreamBuffer(const StreamBuffer &buf);
41    virtual StreamBuffer &operator=(const StreamBuffer &other);
42    virtual ~StreamBuffer() = default;
43    void Reset();
44    void Clean();
45    bool Read(std::string &buf);
46    bool Read(StreamBuffer &buf);
47    bool Read(char *buf, size_t size);
48    bool Write(const std::string &buf);
49    bool Write(const StreamBuffer &buf);
50    virtual bool Write(const char *buf, size_t size);
51    const std::string &GetErrorStatusRemark() const;
52    bool ChkRWError() const;
53#ifndef OHOS_BUILD_ENABLE_RUST
54    bool SeekReadPos(size_t n);
55    bool IsEmpty() const;
56    size_t Size() const;
57    size_t UnreadSize() const;
58    size_t GetAvailableBufSize() const;
59    const char *Data() const;
60    const char *WriteBuf() const;
61#endif // OHOS_BUILD_ENABLE_RUST
62    template<typename T>
63    bool Read(T &data);
64    template<typename T>
65    bool Write(const T &data);
66    template<typename T>
67    bool Read(std::vector<T> &data);
68    template<typename T>
69    bool Write(const std::vector<T> &data);
70    const char *ReadBuf() const;
71
72    template<typename T>
73    StreamBuffer &operator >> (T &data);
74    template<typename T>
75    StreamBuffer &operator << (const T &data);
76    DISALLOW_MOVE(StreamBuffer);
77
78protected:
79    bool Clone(const StreamBuffer &buf);
80#ifdef OHOS_BUILD_ENABLE_RUST
81public:
82    std::unique_ptr<RustStreamBuffer, void(*)(RustStreamBuffer*)> streamBufferPtr_ { StreamBufferCreate(),
83        StreamBufferDelete };
84#else
85    enum class ErrorStatus {
86        ERROR_STATUS_OK,
87        ERROR_STATUS_READ,
88        ERROR_STATUS_WRITE,
89    };
90    ErrorStatus rwErrorStatus_ = ErrorStatus::ERROR_STATUS_OK;
91    size_t rCount_ { 0 };
92    size_t wCount_ { 0 };
93    size_t rPos_ { 0 };
94    size_t wPos_ { 0 };
95    char szBuff_[MAX_STREAM_BUF_SIZE + 1] = {};
96#endif // OHOS_BUILD_ENABLE_RUST
97};
98
99template<typename T>
100bool StreamBuffer::Read(T &data)
101{
102    if (!Read(reinterpret_cast<char *>(&data), sizeof(data))) {
103#ifdef OHOS_BUILD_ENABLE_RUST
104        const char *s = StreamBufferGetErrorStatusRemark(streamBufferPtr_.get());
105        SEN_HILOGE("[%{public}s] size:%{public}zu count:%{public}d",
106            s, sizeof(data), StreamBufferGetRcount(streamBufferPtr_.get()) + 1);
107#else
108        SEN_HILOGE("%{public}s, size:%{public}zu, count:%{public}zu",
109            GetErrorStatusRemark().c_str(), sizeof(data), rCount_ + 1);
110#endif // OHOS_BUILD_ENABLE_RUST
111        return false;
112    }
113    return true;
114}
115
116template<typename T>
117bool StreamBuffer::Write(const T &data)
118{
119    if (!Write(reinterpret_cast<const char *>(&data), sizeof(data))) {
120#ifdef OHOS_BUILD_ENABLE_RUST
121        const char *s = StreamBufferGetErrorStatusRemark(streamBufferPtr_.get());
122        SEN_HILOGE("[%{public}s] size:%{public}zu,count:%{public}d",
123            s, sizeof(data), StreamBufferGetWcount(streamBufferPtr_.get()) + 1);
124#else
125        SEN_HILOGE("%{public}s, size:%{public}zu, count:%{public}zu",
126            GetErrorStatusRemark().c_str(), sizeof(data), wCount_ + 1);
127#endif // OHOS_BUILD_ENABLE_RUST
128        return false;
129    }
130    return true;
131}
132
133template<typename T>
134bool StreamBuffer::Read(std::vector<T> &data)
135{
136    size_t size = 0;
137    if (!Read(size)) {
138        SEN_HILOGE("Read vector size failed");
139        return false;
140    }
141    if (size > MAX_VECTOR_SIZE) {
142        SEN_HILOGE("Vector size is invalid, size:%{public}zu", size);
143        return false;
144    }
145    for (size_t i = 0; i < size; i++) {
146        T val;
147        if (!Read(val)) {
148            SEN_HILOGE("Read vector data failed");
149            return false;
150        }
151        data.push_back(val);
152    }
153    return true;
154}
155
156template<typename T>
157bool StreamBuffer::Write(const std::vector<T> &data)
158{
159    if (data.size() > INT32_MAX) {
160        SEN_HILOGE("Vector exceeds the max range");
161        return false;
162    }
163    size_t size = data.size();
164    if (!Write(size)) {
165        SEN_HILOGE("Write vector size failed");
166        return false;
167    }
168    for (const auto &item : data) {
169        if (!Write(item)) {
170            SEN_HILOGE("Write vector data failed");
171            return false;
172        }
173    }
174    return true;
175}
176
177template<typename T>
178StreamBuffer &StreamBuffer::operator>>(T &data)
179{
180    if (!Read(data)) {
181        SEN_HILOGW("Read data failed");
182    }
183    return *this;
184}
185
186template<typename T>
187StreamBuffer &StreamBuffer::operator<<(const T &data)
188{
189    if (!Write(data)) {
190        SEN_HILOGW("Write data failed");
191    }
192    return *this;
193}
194} // namespace Sensors
195} // namespace OHOS
196#endif // STREAM_BUFFER_H