mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Roll forward to cl/314747126
Signed-off-by: Alexey Polyudov <apolyudov@google.com> Change-Id: Ie19e006429b138b3768e97dae971a43fdc5ef8bf
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("//ads/util/non_compile:non_compile.bzl", "cc_with_non_compile_test")
|
||||
|
||||
cc_library(
|
||||
name = "base",
|
||||
srcs = [
|
||||
"base64_utils.cc",
|
||||
"prng.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"base64_utils.h",
|
||||
"byte_array.h",
|
||||
"callable.h",
|
||||
"exception.h",
|
||||
"input_stream.h",
|
||||
"listeners.h",
|
||||
"output_stream.h",
|
||||
"prng.h",
|
||||
"runnable.h",
|
||||
"socket.h",
|
||||
],
|
||||
visibility = [
|
||||
"//core_v2:__subpackages__",
|
||||
"//platform_v2:__subpackages__",
|
||||
"//platform_v2/api:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/strings",
|
||||
"//absl/time",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "util",
|
||||
srcs = [
|
||||
"base_input_stream.cc",
|
||||
"base_pipe.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"base_input_stream.h",
|
||||
"base_mutex_lock.h",
|
||||
"base_pipe.h",
|
||||
],
|
||||
visibility = [
|
||||
"//platform_v2/impl:__subpackages__",
|
||||
"//platform_v2/public:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":base",
|
||||
"//platform_v2/api:types",
|
||||
"//absl/base:core_headers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "logging",
|
||||
hdrs = [
|
||||
"logging.h",
|
||||
],
|
||||
visibility = [
|
||||
"//platform_v2:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//platform:logging",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "test_util",
|
||||
testonly = True,
|
||||
srcs = [
|
||||
"medium_environment.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"medium_environment.h",
|
||||
],
|
||||
visibility = [
|
||||
"//core_v2:__subpackages__",
|
||||
"//platform_v2/impl:__subpackages__",
|
||||
"//platform_v2/public:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":base",
|
||||
":logging",
|
||||
"//platform_v2/api:comm",
|
||||
"//platform_v2/public:types",
|
||||
"//absl/container:flat_hash_map",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "platform_base_test",
|
||||
srcs = [
|
||||
"byte_array_test.cc",
|
||||
"prng_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":base",
|
||||
"//testing/base/public:gunit_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_with_non_compile_test(
|
||||
name = "exception_test",
|
||||
srcs = [
|
||||
"exception_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":base",
|
||||
"//testing/base/public:gunit_main",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform_v2/base/base64_utils.h"
|
||||
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
std::string Base64Utils::Encode(const ByteArray& bytes) {
|
||||
std::string base64_string;
|
||||
|
||||
absl::WebSafeBase64Escape(std::string(bytes), &base64_string);
|
||||
|
||||
return base64_string;
|
||||
}
|
||||
|
||||
ByteArray Base64Utils::Decode(absl::string_view base64_string) {
|
||||
std::string decoded_string;
|
||||
if (!absl::WebSafeBase64Unescape(base64_string, &decoded_string)) {
|
||||
return ByteArray();
|
||||
}
|
||||
|
||||
return ByteArray(decoded_string.data(), decoded_string.size());
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_BASE64_UTILS_H_
|
||||
#define PLATFORM_V2_BASE_BASE64_UTILS_H_
|
||||
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
class Base64Utils {
|
||||
public:
|
||||
static std::string Encode(const ByteArray& bytes);
|
||||
static ByteArray Decode(absl::string_view base64_string);
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_BASE64_UTILS_H_
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform_v2/base/base_input_stream.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
ExceptionOr<ByteArray> BaseInputStream::Read(std::int64_t size) {
|
||||
if (!IsAvailable(size)) {
|
||||
return ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
|
||||
ByteArray read_bytes{static_cast<size_t>(size)};
|
||||
if (read_bytes.CopyAt(/*offset=*/0, buffer_,
|
||||
/*source_offset=*/position_)) {
|
||||
position_ += size;
|
||||
return ExceptionOr<ByteArray>{read_bytes};
|
||||
} else {
|
||||
return ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
}
|
||||
|
||||
std::uint8_t BaseInputStream::ReadUint8() {
|
||||
constexpr int byte_size = sizeof(std::uint8_t);
|
||||
ByteArray read_bytes = ReadBytes(byte_size);
|
||||
if (read_bytes.Empty() || read_bytes.size() != byte_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return read_bytes.data()[0];
|
||||
}
|
||||
|
||||
std::uint16_t BaseInputStream::ReadUint16() {
|
||||
constexpr int byte_size = sizeof(std::uint16_t);
|
||||
ByteArray read_bytes = ReadBytes(byte_size);
|
||||
if (read_bytes.Empty() || read_bytes.size() != byte_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Convert from network order.
|
||||
const char *data = read_bytes.data();
|
||||
return static_cast<uint16_t>(data[0]) << 8 | static_cast<uint16_t>(data[1]);
|
||||
}
|
||||
|
||||
std::uint32_t BaseInputStream::ReadUint32() {
|
||||
constexpr int byte_size = sizeof(std::uint32_t);
|
||||
ByteArray read_bytes = ReadBytes(byte_size);
|
||||
if (read_bytes.Empty() || read_bytes.size() != byte_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Convert from network order.
|
||||
const char *data = read_bytes.data();
|
||||
return static_cast<uint32_t>(data[0]) << 24 |
|
||||
static_cast<uint32_t>(data[1]) << 16 |
|
||||
static_cast<uint32_t>(data[2]) << 8 | static_cast<uint32_t>(data[3]);
|
||||
}
|
||||
|
||||
std::uint64_t BaseInputStream::ReadUint64() {
|
||||
constexpr int byte_size = sizeof(std::uint64_t);
|
||||
ByteArray read_bytes = ReadBytes(byte_size);
|
||||
if (read_bytes.Empty() || read_bytes.size() != byte_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Convert from network order.
|
||||
const char *data = read_bytes.data();
|
||||
return static_cast<uint64_t>(data[0]) << 56 |
|
||||
static_cast<uint64_t>(data[1]) << 48 |
|
||||
static_cast<uint64_t>(data[2]) << 40 |
|
||||
static_cast<uint64_t>(data[3]) << 32 |
|
||||
static_cast<uint64_t>(data[4]) << 24 |
|
||||
static_cast<uint64_t>(data[5]) << 16 |
|
||||
static_cast<uint64_t>(data[6]) << 8 | static_cast<uint64_t>(data[7]);
|
||||
}
|
||||
|
||||
ByteArray BaseInputStream::ReadBytes(int size) {
|
||||
ExceptionOr<ByteArray> read_bytes_result = Read(size);
|
||||
if (!read_bytes_result.ok()) {
|
||||
return ByteArray{};
|
||||
}
|
||||
|
||||
return read_bytes_result.GetResult();
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_BASE_INPUT_STREAM_H_
|
||||
#define PLATFORM_V2_BASE_BASE_INPUT_STREAM_H_
|
||||
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
#include "platform_v2/base/exception.h"
|
||||
#include "platform_v2/base/input_stream.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// A base {@link InputStream } for reading the contents of a byte array.
|
||||
class BaseInputStream : public InputStream {
|
||||
public:
|
||||
explicit BaseInputStream(ByteArray &buffer) : buffer_{buffer} {}
|
||||
BaseInputStream(const BaseInputStream &) = delete;
|
||||
BaseInputStream &operator=(const BaseInputStream &) = delete;
|
||||
~BaseInputStream() override { Close(); }
|
||||
|
||||
ExceptionOr<ByteArray> Read(std::int64_t size) override;
|
||||
|
||||
Exception Close() override {
|
||||
// Do nothing.
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
std::uint8_t ReadUint8();
|
||||
std::uint16_t ReadUint16();
|
||||
std::uint32_t ReadUint32();
|
||||
std::uint64_t ReadUint64();
|
||||
bool IsAvailable(int size) const {
|
||||
return buffer_.size() - position_ >= size;
|
||||
}
|
||||
|
||||
private:
|
||||
ByteArray ReadBytes(int size);
|
||||
|
||||
ByteArray &buffer_;
|
||||
int position_{0};
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_BASE_INPUT_STREAM_H_
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_BASE_MUTEX_LOCK_H_
|
||||
#define PLATFORM_V2_BASE_BASE_MUTEX_LOCK_H_
|
||||
|
||||
#include "platform_v2/api/mutex.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// An RAII mechanism to acquire a Lock over a block of code.
|
||||
class ABSL_SCOPED_LOCKABLE BaseMutexLock final {
|
||||
public:
|
||||
explicit BaseMutexLock(api::Mutex* mutex) ABSL_EXCLUSIVE_LOCK_FUNCTION(mutex)
|
||||
: mutex_(mutex) {
|
||||
mutex_->Lock();
|
||||
}
|
||||
~BaseMutexLock() ABSL_UNLOCK_FUNCTION() { mutex_->Unlock(); }
|
||||
|
||||
private:
|
||||
api::Mutex* mutex_;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_BASE_MUTEX_LOCK_H_
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform_v2/base/base_pipe.h"
|
||||
|
||||
#include "platform_v2/base/base_mutex_lock.h"
|
||||
#include "platform_v2/base/input_stream.h"
|
||||
#include "platform_v2/base/output_stream.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
ExceptionOr<ByteArray> BasePipe::Read(size_t size) {
|
||||
BaseMutexLock lock(mutex_.get());
|
||||
|
||||
// We're done reading all the chunks that were written before the OutputStream
|
||||
// was closed, so there's nothing to do here other than return an empty chunk
|
||||
// to serve as an EOF indication to callers.
|
||||
if (read_all_chunks_) {
|
||||
return ExceptionOr<ByteArray>{ByteArray{}};
|
||||
}
|
||||
|
||||
while (buffer_.empty() && !input_stream_closed_) {
|
||||
Exception wait_exception = cond_->Wait();
|
||||
|
||||
if (wait_exception.Raised()) {
|
||||
return ExceptionOr<ByteArray>{wait_exception};
|
||||
}
|
||||
}
|
||||
|
||||
if (input_stream_closed_) {
|
||||
return ExceptionOr<ByteArray>{Exception::kIo};
|
||||
}
|
||||
|
||||
ByteArray first_chunk{buffer_.front()};
|
||||
buffer_.pop_front();
|
||||
|
||||
// If we received our sentinel chunk, mark the fact that there cannot
|
||||
// possibly be any more chunks to read here on in, and return an empty chunk
|
||||
// to serve as an EOF indication to callers.
|
||||
if (first_chunk.Empty()) {
|
||||
read_all_chunks_ = true;
|
||||
return ExceptionOr<ByteArray>{ByteArray{}};
|
||||
}
|
||||
|
||||
// If first_chunk is small enough to not overshoot the requested 'size', just
|
||||
// return that.
|
||||
if (first_chunk.size() <= size) {
|
||||
return ExceptionOr<ByteArray>{first_chunk};
|
||||
} else {
|
||||
// Break first_chunk into 2 parts -- the first one of which (next_chunk)
|
||||
// will be 'size' bytes long, and will be returned, and the second one of
|
||||
// which (overflow_chunk) will be re-inserted into buffer_, at the head of
|
||||
// the queue, to be served up in the next call to read().
|
||||
ByteArray next_chunk(first_chunk.data(), size);
|
||||
buffer_.push_front(
|
||||
ByteArray(first_chunk.data() + size, first_chunk.size() - size));
|
||||
return ExceptionOr<ByteArray>{next_chunk};
|
||||
}
|
||||
}
|
||||
|
||||
Exception BasePipe::Write(const ByteArray& data) {
|
||||
BaseMutexLock lock(mutex_.get());
|
||||
|
||||
return WriteLocked(data);
|
||||
}
|
||||
|
||||
void BasePipe::MarkInputStreamClosed() {
|
||||
BaseMutexLock lock(mutex_.get());
|
||||
|
||||
input_stream_closed_ = true;
|
||||
// Trigger cond_ to unblock a potentially-blocked call to read(), and to let
|
||||
// it know to return Exception::IO.
|
||||
cond_->Notify();
|
||||
}
|
||||
|
||||
void BasePipe::MarkOutputStreamClosed() {
|
||||
BaseMutexLock lock(mutex_.get());
|
||||
|
||||
// Write a sentinel null chunk before marking output_stream_closed as true.
|
||||
WriteLocked(ByteArray{});
|
||||
output_stream_closed_ = true;
|
||||
}
|
||||
|
||||
Exception BasePipe::WriteLocked(const ByteArray& data) {
|
||||
if (input_stream_closed_ || output_stream_closed_) {
|
||||
return {Exception::kIo};
|
||||
}
|
||||
|
||||
buffer_.push_back(data);
|
||||
// Trigger cond_ to unblock a potentially-blocked call to read(), now that
|
||||
// there's more data for it to consume.
|
||||
cond_->Notify();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,142 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_BASE_PIPE_H_
|
||||
#define PLATFORM_V2_BASE_BASE_PIPE_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
|
||||
#include "platform_v2/api/condition_variable.h"
|
||||
#include "platform_v2/api/mutex.h"
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
#include "platform_v2/base/exception.h"
|
||||
#include "platform_v2/base/input_stream.h"
|
||||
#include "platform_v2/base/output_stream.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// Common Pipe implenentation.
|
||||
// It does not depend on platform implementation, and this allows it to
|
||||
// be used in the platform implementation itself.
|
||||
// Concrete class must be derived from it, as follows:
|
||||
//
|
||||
// class DerivedPipe : public BasePipe {
|
||||
// public:
|
||||
// DerivedPipe() {
|
||||
// auto mutex = /* construct platform-dependent mutex */;
|
||||
// auto cond = /* construct platform-dependent condition variable */;
|
||||
// Setup(std::move(mutex), std::move(cond));
|
||||
// }
|
||||
// ~DerivedPipe() override = default;
|
||||
// DerivedPipe(DerivedPipe&&) = default;
|
||||
// DerivedPipe& operator=(DerivedPipe&&) = default;
|
||||
// };
|
||||
class BasePipe {
|
||||
public:
|
||||
static constexpr const size_t kChunkSize = 64 * 1024;
|
||||
virtual ~BasePipe() = default;
|
||||
|
||||
// Pipe is not copyable or movable, because copy/move will invalidate
|
||||
// references to input and output streams.
|
||||
// If move is required, Pipe could be wrapped with std::unique_ptr<>.
|
||||
BasePipe(BasePipe&&) = delete;
|
||||
BasePipe& operator=(BasePipe&&) = delete;
|
||||
|
||||
// Get...() methods return references to input and output steam facades.
|
||||
// It is safe to call Get...() methods multiple times.
|
||||
InputStream& GetInputStream() { return input_stream_; }
|
||||
OutputStream& GetOutputStream() { return output_stream_; }
|
||||
|
||||
protected:
|
||||
BasePipe() = default;
|
||||
|
||||
void Setup(std::unique_ptr<api::Mutex> mutex,
|
||||
std::unique_ptr<api::ConditionVariable> cond) {
|
||||
mutex_ = std::move(mutex);
|
||||
cond_ = std::move(cond);
|
||||
}
|
||||
|
||||
private:
|
||||
class BasePipeInputStream : public InputStream {
|
||||
public:
|
||||
explicit BasePipeInputStream(BasePipe* pipe) : pipe_(pipe) {}
|
||||
~BasePipeInputStream() override { DoClose(); }
|
||||
|
||||
ExceptionOr<ByteArray> Read(std::int64_t size) override {
|
||||
return pipe_->Read(size);
|
||||
}
|
||||
Exception Close() override {
|
||||
return DoClose();
|
||||
}
|
||||
|
||||
private:
|
||||
Exception DoClose() {
|
||||
pipe_->MarkInputStreamClosed();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
BasePipe* pipe_;
|
||||
};
|
||||
class BasePipeOutputStream : public OutputStream {
|
||||
public:
|
||||
explicit BasePipeOutputStream(BasePipe* pipe) : pipe_(pipe) {}
|
||||
~BasePipeOutputStream() override { DoClose(); }
|
||||
|
||||
Exception Write(const ByteArray& data) override {
|
||||
return pipe_->Write(data);
|
||||
}
|
||||
Exception Flush() override { return {Exception::kSuccess}; }
|
||||
Exception Close() override {
|
||||
return DoClose();
|
||||
}
|
||||
|
||||
private:
|
||||
Exception DoClose() {
|
||||
pipe_->MarkOutputStreamClosed();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
BasePipe* pipe_;
|
||||
};
|
||||
|
||||
ExceptionOr<ByteArray> Read(size_t size) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
Exception Write(const ByteArray& data) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
void MarkInputStreamClosed() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void MarkOutputStreamClosed() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
Exception WriteLocked(const ByteArray& data)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Order of declaration matters:
|
||||
// - mutex must be defined before condvar;
|
||||
// - input & output streams must be after both mutex and condvar.
|
||||
bool input_stream_closed_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
bool output_stream_closed_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
bool read_all_chunks_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
|
||||
std::deque<ByteArray> ABSL_GUARDED_BY(mutex_) buffer_;
|
||||
std::unique_ptr<api::Mutex> mutex_;
|
||||
std::unique_ptr<api::ConditionVariable> cond_;
|
||||
|
||||
BasePipeInputStream input_stream_{this};
|
||||
BasePipeOutputStream output_stream_{this};
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_BASE_PIPE_H_
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_BYTE_ARRAY_H_
|
||||
#define PLATFORM_V2_BASE_BYTE_ARRAY_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
class ByteArray {
|
||||
public:
|
||||
// Create an empty ByteArray
|
||||
ByteArray() = default;
|
||||
ByteArray(const ByteArray&) = default;
|
||||
ByteArray& operator=(const ByteArray&) = default;
|
||||
ByteArray(ByteArray&&) = default;
|
||||
ByteArray& operator=(ByteArray&&) = default;
|
||||
|
||||
// Create ByteArray from string.
|
||||
explicit ByteArray(absl::string_view source) {
|
||||
SetData(source.data(), source.size());
|
||||
}
|
||||
|
||||
// Create default-initialized ByteArray of a given size.
|
||||
explicit ByteArray(size_t size) { SetData(size); }
|
||||
|
||||
// Create value-initialized ByteArray of a given size.
|
||||
ByteArray(const char* data, size_t size) { SetData(data, size); }
|
||||
|
||||
// Assign a new value to this ByteArray, as a copy of data, with a given size.
|
||||
void SetData(const char* data, size_t size) {
|
||||
if (data == nullptr) {
|
||||
size = 0;
|
||||
}
|
||||
data_.assign(data, size);
|
||||
}
|
||||
|
||||
// Assign a new value of a given size to this ByteArray
|
||||
// (as a repeated char value).
|
||||
void SetData(size_t size, char value = 0) { data_.assign(size, value); }
|
||||
|
||||
// Returns true, if changes were performed to container, false otherwise.
|
||||
bool CopyAt(size_t offset, const ByteArray& from, size_t source_offset = 0) {
|
||||
if (offset >= size()) return false;
|
||||
if (source_offset >= from.size()) return false;
|
||||
memcpy(data() + offset, from.data() + source_offset,
|
||||
std::min(size() - offset, from.size() - source_offset));
|
||||
return true;
|
||||
}
|
||||
|
||||
char* data() { return &data_[0]; }
|
||||
const char* data() const { return data_.data(); }
|
||||
size_t size() const { return data_.size(); }
|
||||
bool Empty() const { return data_.empty(); }
|
||||
|
||||
friend bool operator==(const ByteArray& lhs, const ByteArray& rhs);
|
||||
friend bool operator!=(const ByteArray& lhs, const ByteArray& rhs);
|
||||
friend bool operator<(const ByteArray& lhs, const ByteArray& rhs);
|
||||
|
||||
explicit operator std::string() const { return data_; }
|
||||
|
||||
private:
|
||||
std::string data_;
|
||||
};
|
||||
|
||||
inline bool operator==(const ByteArray& lhs, const ByteArray& rhs) {
|
||||
return lhs.data_ == rhs.data_;
|
||||
}
|
||||
|
||||
inline bool operator!=(const ByteArray& lhs, const ByteArray& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator<(const ByteArray& lhs, const ByteArray& rhs) {
|
||||
return lhs.data_ < rhs.data_;
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_BYTE_ARRAY_H_
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using location::nearby::ByteArray;
|
||||
|
||||
TEST(ByteArrayTest, DefaultSizeIsZero) {
|
||||
ByteArray bytes;
|
||||
EXPECT_EQ(0, bytes.size());
|
||||
}
|
||||
|
||||
TEST(ByteArrayTest, DefaultIsEmpty) {
|
||||
ByteArray bytes;
|
||||
EXPECT_TRUE(bytes.Empty());
|
||||
}
|
||||
|
||||
TEST(ByteArrayTest, NullArrayIsEmpty) {
|
||||
ByteArray bytes{nullptr, 5};
|
||||
EXPECT_TRUE(bytes.Empty());
|
||||
}
|
||||
|
||||
TEST(ByteArrayTest, CopyAtDoesNotExtendArray) {
|
||||
ByteArray v1("12345");
|
||||
ByteArray v2("ABCDEFGH");
|
||||
EXPECT_TRUE(v2.CopyAt(/*offset=*/5, v1));
|
||||
EXPECT_TRUE(v2.CopyAt(/*offset=*/1, v1, /*source_offset=*/3));
|
||||
EXPECT_EQ(v2, ByteArray("A45DE123"));
|
||||
}
|
||||
|
||||
TEST(ByteArrayTest, CopyAtOutOfBoundsIsIgnored) {
|
||||
ByteArray v1("12345");
|
||||
ByteArray v2("ABCDEFGH");
|
||||
// Try to do an out-of-bounds read.
|
||||
EXPECT_FALSE(v2.CopyAt(/* offset=*/5, v1, /*source_offset=*/10));
|
||||
// Try to do an out-of-bounds write.
|
||||
EXPECT_FALSE(v2.CopyAt(/* offset=*/9, v1));
|
||||
EXPECT_EQ(v2, ByteArray("ABCDEFGH"));
|
||||
}
|
||||
|
||||
TEST(ByteArrayTest, SetFromString) {
|
||||
std::string setup("setup_test");
|
||||
ByteArray bytes{setup}; // array initialized with a copy of string.
|
||||
EXPECT_EQ(setup.size(), bytes.size());
|
||||
EXPECT_EQ(std::string(bytes), setup);
|
||||
}
|
||||
|
||||
TEST(ByteArrayTest, SetExplicitSize) {
|
||||
constexpr size_t kArraySize = 10;
|
||||
char reference[kArraySize]{};
|
||||
ByteArray bytes{kArraySize}; // array of size 10, zero-initialized.
|
||||
EXPECT_EQ(kArraySize, bytes.size());
|
||||
EXPECT_EQ(0, memcmp(bytes.data(), reference, kArraySize));
|
||||
}
|
||||
|
||||
TEST(ByteArrayTest, SetExplicitData) {
|
||||
constexpr static const char message[]{"test_message"};
|
||||
constexpr size_t kMessageSize = sizeof(message);
|
||||
ByteArray bytes{message, kMessageSize};
|
||||
EXPECT_EQ(kMessageSize, bytes.size());
|
||||
EXPECT_NE(message, bytes.data());
|
||||
EXPECT_EQ(0, memcmp(message, bytes.data(), kMessageSize));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_CALLABLE_H_
|
||||
#define PLATFORM_V2_BASE_CALLABLE_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "platform_v2/base/exception.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// The Callable is and object intended to be executed by a thread, that is able
|
||||
// to return a value of specified type T.
|
||||
// It must be invokable without arguments. It must return a value implicitly
|
||||
// convertible to ExceptionOr<T>.
|
||||
//
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html
|
||||
template <typename T>
|
||||
using Callable = std::function<ExceptionOr<T>()>;
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_CALLABLE_H_
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_EXCEPTION_H_
|
||||
#define PLATFORM_V2_BASE_EXCEPTION_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "absl/meta/type_traits.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
struct Exception {
|
||||
enum Value : int {
|
||||
kFailed = -1, // Initial value of Exception; any unknown error.
|
||||
kSuccess = 0, // No exception.
|
||||
kIo = 1, // IO Error happened.
|
||||
kInterrupted = 2, // Operation was interrupted.
|
||||
kInvalidProtocolBuffer = 3, // Couldn't parse.
|
||||
kExecution = 4, // Couldn't execute.
|
||||
kTimeout = 5, // Operarion did not finish within specified time.
|
||||
};
|
||||
bool Ok() const { return value == kSuccess; }
|
||||
bool Raised() const { return !Ok(); }
|
||||
bool Raised(Value value) const { return this->value == value; }
|
||||
Value value{kFailed};
|
||||
};
|
||||
|
||||
constexpr inline bool operator==(const Exception& a, const Exception& b) {
|
||||
return a.value == b.value;
|
||||
}
|
||||
|
||||
constexpr inline bool operator!=(const Exception& a, const Exception& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
// ExceptionOr provides experience similar to StatusOr<T> used in
|
||||
// Google Cloud API, see:
|
||||
// https://googleapis.github.io/google-cloud-cpp/0.7.0/common/status__or_8h_source.html
|
||||
//
|
||||
// If ok() returns true, result() is a usable return value. Otherwise,
|
||||
// exception() explains why such a value is not present.
|
||||
//
|
||||
// A typical pattern of usage is as follows:
|
||||
//
|
||||
// if (!e.ok()) {
|
||||
// if (Exception::EXCEPTION_TYPE_1 == e.exception()) {
|
||||
// // Handle Exception::EXCEPTION_TYPE_1.
|
||||
// } else if (Exception::EXCEPTION_TYPE_2 == e.exception()) {
|
||||
// // Handle Exception::EXCEPTION_TYPE_2.
|
||||
// }
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // Use e.result().
|
||||
template <typename T>
|
||||
class ExceptionOr {
|
||||
public:
|
||||
ExceptionOr() = default;
|
||||
explicit ExceptionOr(T&& result)
|
||||
: result_{std::move(result)},
|
||||
exception_{Exception::kSuccess} {} // NOLINT
|
||||
explicit ExceptionOr(const T& result)
|
||||
: result_{result}, exception_{Exception::kSuccess} {} // NOLINT
|
||||
ExceptionOr(Exception::Value exception) : exception_{exception} {} // NOLINT
|
||||
ExceptionOr(Exception exception) : exception_{exception} {} // NOLINT
|
||||
// If there exists explicit conversion from from U to T,
|
||||
// then allow explicit conversion from ExceptionOr<U> to ExceptionOr<T>.
|
||||
template <typename U, typename = absl::void_t<decltype(T{std::declval<U>()})>>
|
||||
explicit ExceptionOr<T>(ExceptionOr<U> value) {
|
||||
if (!value.ok()) {
|
||||
exception_ = value.GetException();
|
||||
} else {
|
||||
result_ = T{std::move(value.result())};
|
||||
exception_ = Exception{Exception::kSuccess};
|
||||
}
|
||||
}
|
||||
|
||||
bool ok() const { return exception_.value == Exception::kSuccess; }
|
||||
|
||||
T& result() & { return result_; }
|
||||
const T& result() const& { return result_; }
|
||||
T&& result() && { return std::move(result_); }
|
||||
const T&& result() const&& { return std::move(result_); }
|
||||
|
||||
Exception::Value exception() const { return exception_.value; }
|
||||
|
||||
T GetResult() const { return result_; }
|
||||
Exception GetException() const { return exception_; }
|
||||
|
||||
private:
|
||||
T result_{};
|
||||
Exception exception_{Exception::kFailed};
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_EXCEPTION_H_
|
||||
@@ -0,0 +1,120 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform_v2/base/exception.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "platform_v2/base/exception_test.nc.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace location::nearby {
|
||||
|
||||
TEST(ExceptionOr, Result_Copy_NonConst) {
|
||||
ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
|
||||
// Expect a copy when not explicitly moving the result.
|
||||
std::vector<int> copy = exception_or_vector.result();
|
||||
EXPECT_FALSE(copy.empty());
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
|
||||
// Modifying |exception_or_vector| should not affect the copy.
|
||||
exception_or_vector.result().clear();
|
||||
EXPECT_FALSE(copy.empty());
|
||||
}
|
||||
|
||||
TEST(ExceptionOr, Result_Copy_Const) {
|
||||
const ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
|
||||
// Expect a copy when not explicitly moving the result.
|
||||
std::vector<int> copy = exception_or_vector.result();
|
||||
EXPECT_FALSE(copy.empty());
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
}
|
||||
|
||||
TEST(ExceptionOr, Result_Reference_NonConst) {
|
||||
ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
|
||||
// Getting a reference should not modify the source.
|
||||
std::vector<int>& reference = exception_or_vector.result();
|
||||
EXPECT_FALSE(reference.empty());
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
|
||||
// Modifying |exception_or_vector| should reflect in the reference.
|
||||
exception_or_vector.result().clear();
|
||||
EXPECT_TRUE(reference.empty());
|
||||
}
|
||||
|
||||
TEST(ExceptionOr, Result_Reference_Const) {
|
||||
const ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
|
||||
// Getting a reference should not modify the source.
|
||||
const std::vector<int>& reference = exception_or_vector.result();
|
||||
EXPECT_FALSE(reference.empty());
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
}
|
||||
|
||||
TEST(ExceptionOr, Result_Move_NonConst) {
|
||||
ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
|
||||
// Moving the result should clear the source.
|
||||
std::vector<int> moved = std::move(exception_or_vector).result();
|
||||
EXPECT_FALSE(moved.empty());
|
||||
}
|
||||
|
||||
TEST(ExceptionOr, Result_Move_Const) {
|
||||
const ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
|
||||
EXPECT_FALSE(exception_or_vector.result().empty());
|
||||
|
||||
// Moving const rvalue reference will result in a copy.
|
||||
std::vector<int> moved = std::move(exception_or_vector).result();
|
||||
EXPECT_FALSE(moved.empty());
|
||||
}
|
||||
|
||||
TEST(ExceptionOr, ExplicitConversionWorks) {
|
||||
class A {
|
||||
public:
|
||||
A() = default;
|
||||
};
|
||||
class B {
|
||||
public:
|
||||
B() = default;
|
||||
explicit B(A) {}
|
||||
};
|
||||
ExceptionOr<A> a(A{});
|
||||
ExceptionOr<B> b(a);
|
||||
EXPECT_TRUE(a.ok());
|
||||
EXPECT_TRUE(b.ok());
|
||||
}
|
||||
|
||||
TEST(ExceptionOr, ExplicitConversionFailsToCompile) {
|
||||
class A {
|
||||
public:
|
||||
A() = default;
|
||||
};
|
||||
class B {
|
||||
public:
|
||||
B() = default;
|
||||
};
|
||||
ExceptionOr<A> a(A{});
|
||||
EXPECT_NON_COMPILE("no matching constructor", { ExceptionOr<B> b(a); });
|
||||
}
|
||||
|
||||
} // namespace location::nearby
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_INPUT_STREAM_H_
|
||||
#define PLATFORM_V2_BASE_INPUT_STREAM_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
#include "platform_v2/base/exception.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// An InputStream represents an input stream of bytes.
|
||||
//
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html
|
||||
class InputStream {
|
||||
public:
|
||||
virtual ~InputStream() = default;
|
||||
|
||||
// throws Exception::kIo
|
||||
virtual ExceptionOr<ByteArray> Read(std::int64_t size) = 0;
|
||||
// throws Exception::kIo
|
||||
virtual Exception Close() = 0;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_INPUT_STREAM_H_
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_LISTENERS_H_
|
||||
#define PLATFORM_V2_BASE_LISTENERS_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// Provides default-initialization with a valid empty method,
|
||||
// instead of nullptr. This allows partial initialization
|
||||
// of a set of listeners.
|
||||
template <typename... Args>
|
||||
constexpr std::function<void(Args...)> DefaultCallback() {
|
||||
return std::function<void(Args...)>{[](Args...) {}};
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_LISTENERS_H_
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_LOGGING_H_
|
||||
#define PLATFORM_V2_BASE_LOGGING_H_
|
||||
|
||||
#include "platform/logging.h"
|
||||
|
||||
#endif // PLATFORM_V2_BASE_LOGGING_H_
|
||||
@@ -0,0 +1,226 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform_v2/base/medium_environment.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cinttypes>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
|
||||
#include "platform_v2/api/bluetooth_adapter.h"
|
||||
#include "platform_v2/api/bluetooth_classic.h"
|
||||
#include "platform_v2/base/logging.h"
|
||||
#include "platform_v2/public/count_down_latch.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
MediumEnvironment& MediumEnvironment::Instance() {
|
||||
static std::aligned_storage_t<sizeof(MediumEnvironment),
|
||||
alignof(MediumEnvironment)>
|
||||
storage;
|
||||
static MediumEnvironment* env = new (&storage) MediumEnvironment();
|
||||
return *env;
|
||||
}
|
||||
|
||||
void MediumEnvironment::Start() {
|
||||
if (!enabled_.exchange(true)) {
|
||||
NEARBY_LOG(INFO, "MediumEnvironment::Start()");
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MediumEnvironment::Stop() {
|
||||
if (enabled_.exchange(false)) {
|
||||
NEARBY_LOG(INFO, "MediumEnvironment::Stop()");
|
||||
Sync(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MediumEnvironment::Reset() {
|
||||
RunOnMediumEnvironmentThread([this]() {
|
||||
NEARBY_LOG(INFO, "MediumEnvironment::Reset()");
|
||||
bluetooth_adapters_.clear();
|
||||
bluetooth_mediums_.clear();
|
||||
});
|
||||
Sync();
|
||||
}
|
||||
|
||||
void MediumEnvironment::Sync(bool enable_notifications) {
|
||||
enable_notifications_ = enable_notifications;
|
||||
NEARBY_LOG(INFO, "MediumEnvironment::sync(%d)", enable_notifications);
|
||||
int count = 0;
|
||||
do {
|
||||
CountDownLatch latch(1);
|
||||
count = job_count_ + 1;
|
||||
// We are about to schedule one last job.
|
||||
// When it is done, counter must be equal to count.
|
||||
// However, if pending jobs schedule anything else,
|
||||
// it will be pending after us.
|
||||
// If we want to ensure we are completely idle, then we have to
|
||||
// repeat sync, until this becomes true.
|
||||
RunOnMediumEnvironmentThread([&latch]() { latch.CountDown(); });
|
||||
latch.Await();
|
||||
} while (count < job_count_);
|
||||
NEARBY_LOG(INFO, "MediumEnvironment::Sync(): done [count=%d]", count);
|
||||
}
|
||||
|
||||
void MediumEnvironment::OnBluetoothAdapterChangedState(
|
||||
api::BluetoothAdapter& adapter, api::BluetoothDevice& adapter_device,
|
||||
std::string name, bool enabled, api::BluetoothAdapter::ScanMode mode) {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([this, &adapter, &adapter_device,
|
||||
name = std::move(name), enabled, mode]() {
|
||||
NEARBY_LOG(INFO,
|
||||
"[adapter=%p, device=%p] update: name=%s, enabled=%d, mode=%d",
|
||||
&adapter, &adapter_device, name.c_str(), enabled, mode);
|
||||
for (auto& [medium, info] : bluetooth_mediums_) {
|
||||
// Do not send notification to medium that owns this adapter.
|
||||
if (info.adapter == &adapter) continue;
|
||||
NEARBY_LOG(INFO, "[adapter=%p, device=%p] notify: adapter=%p", &adapter,
|
||||
&adapter_device, info.adapter);
|
||||
OnDeviceStateChanged(info, adapter_device, name, mode, enabled);
|
||||
}
|
||||
// We don't care if there is an adapter already since all we store is a
|
||||
// pointer. Pointer must remain valid for the duration of a Core session
|
||||
// (since it is owned by the correspoinding Medium, and mediums lifetime
|
||||
// matches Core lifetime).
|
||||
bluetooth_adapters_.emplace(&adapter, &adapter_device);
|
||||
});
|
||||
}
|
||||
|
||||
void MediumEnvironment::OnDeviceStateChanged(
|
||||
BluetoothMediumContext& info, api::BluetoothDevice& device,
|
||||
const std::string& name, api::BluetoothAdapter::ScanMode mode,
|
||||
bool enabled) {
|
||||
if (!enabled_) return;
|
||||
auto item = info.devices.find(&device);
|
||||
if (item == info.devices.end()) {
|
||||
NEARBY_LOG(
|
||||
INFO, "G3 OnDeviceStateChanged [device impl=%p]: new device; notify=%d",
|
||||
&device, enable_notifications_.load());
|
||||
if (mode == api::BluetoothAdapter::ScanMode::kConnectableDiscoverable &&
|
||||
enabled) {
|
||||
// New device is turned on, and is in discoverable state.
|
||||
// Store device name, and report it as discovered.
|
||||
info.devices.emplace(&device, name);
|
||||
if (enable_notifications_) {
|
||||
RunOnMediumEnvironmentThread(
|
||||
[&info, &device]() { info.callback.device_discovered_cb(device); });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NEARBY_LOG(
|
||||
INFO,
|
||||
"G3 OnDeviceStateChanged [device impl=%p]: exisitng device; notify=%d",
|
||||
&device, enable_notifications_.load());
|
||||
auto& discovered_name = item->second;
|
||||
if (mode == api::BluetoothAdapter::ScanMode::kConnectableDiscoverable &&
|
||||
enabled) {
|
||||
if (name != discovered_name) {
|
||||
// Known device is turned on, and is in discoverable state.
|
||||
// Store device name, and report it as renamed.
|
||||
item->second = name;
|
||||
if (enable_notifications_) {
|
||||
RunOnMediumEnvironmentThread([&info, &device]() {
|
||||
info.callback.device_name_changed_cb(device);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Device is in discovery mode, so we are reporting it anyway.
|
||||
if (enable_notifications_) {
|
||||
RunOnMediumEnvironmentThread([&info, &device]() {
|
||||
info.callback.device_discovered_cb(device);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!enabled) {
|
||||
// Known device is turned off.
|
||||
// Erase it from the map, and report as lost.
|
||||
if (enable_notifications_) {
|
||||
RunOnMediumEnvironmentThread(
|
||||
[&info, &device]() { info.callback.device_lost_cb(device); });
|
||||
}
|
||||
info.devices.erase(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MediumEnvironment::RunOnMediumEnvironmentThread(
|
||||
std::function<void()> runnable) {
|
||||
job_count_++;
|
||||
executor_.Execute(std::move(runnable));
|
||||
}
|
||||
|
||||
void MediumEnvironment::RegisterBluetoothMedium(
|
||||
api::BluetoothClassicMedium& medium,
|
||||
api::BluetoothAdapter& medium_adapter) {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([this, &medium, &medium_adapter]() {
|
||||
auto& context = bluetooth_mediums_
|
||||
.insert({&medium,
|
||||
BluetoothMediumContext{
|
||||
.adapter = &medium_adapter,
|
||||
}})
|
||||
.first->second;
|
||||
auto* owned_adapter = context.adapter;
|
||||
NEARBY_LOG(INFO, "Registered: medium=%p; adapter=%p", &medium,
|
||||
owned_adapter);
|
||||
for (auto& [adapter, device] : bluetooth_adapters_) {
|
||||
if (adapter == nullptr) continue;
|
||||
OnDeviceStateChanged(context, *device, adapter->GetName(),
|
||||
adapter->GetScanMode(), adapter->IsEnabled());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MediumEnvironment::UpdateBluetoothMedium(
|
||||
api::BluetoothClassicMedium& medium, BluetoothDiscoveryCallback callback) {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([this, &medium,
|
||||
callback = std::move(callback)]() {
|
||||
auto item = bluetooth_mediums_.find(&medium);
|
||||
if (item == bluetooth_mediums_.end()) return;
|
||||
auto& context = item->second;
|
||||
context.callback = std::move(callback);
|
||||
auto* owned_adapter = context.adapter;
|
||||
NEARBY_LOG(
|
||||
INFO,
|
||||
"Updated: this=%p; medium=%p; adapter=%p; name=%s; enabled=%d; mode=%d",
|
||||
this, &medium, owned_adapter, owned_adapter->GetName().c_str(),
|
||||
owned_adapter->IsEnabled(), owned_adapter->GetScanMode());
|
||||
for (auto& [adapter, device] : bluetooth_adapters_) {
|
||||
if (adapter == nullptr) continue;
|
||||
OnDeviceStateChanged(context, *device, adapter->GetName(),
|
||||
adapter->GetScanMode(), adapter->IsEnabled());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MediumEnvironment::UnregisterBluetoothMedium(
|
||||
api::BluetoothClassicMedium& medium) {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([this, &medium]() {
|
||||
auto item = bluetooth_mediums_.extract(&medium);
|
||||
if (item.empty()) return;
|
||||
auto& context = item.mapped();
|
||||
NEARBY_LOG(INFO, "Unregistered medium for device=%s",
|
||||
context.adapter->GetName().c_str());
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_MEDIUM_ENVIRONMENT_H_
|
||||
#define PLATFORM_V2_BASE_MEDIUM_ENVIRONMENT_H_
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "platform_v2/api/bluetooth_adapter.h"
|
||||
#include "platform_v2/api/bluetooth_classic.h"
|
||||
#include "platform_v2/base/listeners.h"
|
||||
#include "platform_v2/public/single_thread_executor.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// MediumEnvironment is a simulated environment which allows multiple instances
|
||||
// of simulated HW devices to "work" together as if they are physical.
|
||||
// For each medium type it provides necessary methods to implement
|
||||
// advertising, discovery and establishment of a data link.
|
||||
// NOTE: this code depends on public:types target.
|
||||
class MediumEnvironment {
|
||||
public:
|
||||
using BluetoothDiscoveryCallback =
|
||||
api::BluetoothClassicMedium::DiscoveryCallback;
|
||||
MediumEnvironment(const MediumEnvironment&) = delete;
|
||||
MediumEnvironment& operator=(const MediumEnvironment&) = delete;
|
||||
|
||||
// Creates and returns a reference to the global test environment instance.
|
||||
static MediumEnvironment& Instance();
|
||||
|
||||
// Global ON/OFF switch for medium environment.
|
||||
// Start & Stop work as On/Off switch for this object.
|
||||
// Default state (after creation) is ON, to make it compatible with early
|
||||
// tests that are already using it and relying on it being ON.
|
||||
|
||||
// Enables Medium environment.
|
||||
void Start();
|
||||
// Disables Medium environment.
|
||||
void Stop();
|
||||
|
||||
// Clears state. No notifications are sent.
|
||||
void Reset();
|
||||
|
||||
// Waits for all previously scheduled jobs to finish.
|
||||
// This method works as a barrier that guarantees that after it returns, all
|
||||
// the activities that started before it was called, or while it was running
|
||||
// are ended. This means that system is at the state of relaxation when this
|
||||
// code returns. It requires external stimulus to get out of relaxation state.
|
||||
//
|
||||
// If enable_notifications is true (default), simulation environment
|
||||
// will send all future notification events to all registered objects,
|
||||
// whenever protocol requires that. This is expected behavior.
|
||||
// If enabled_notifications is false, future event notifications will not be
|
||||
// sent to registered instances. This is useful for protocol shutdown,
|
||||
// where we no longer care about notifications, and where notifications may
|
||||
// otherwise be delivered after the notification source or target lifeteme has
|
||||
// ended, and cause undefined behavior.
|
||||
void Sync(bool enable_notifications = true);
|
||||
|
||||
// Adds an adapter to internal container.
|
||||
// Notify BluetoothClassicMediums if any that adapter state has changed.
|
||||
void OnBluetoothAdapterChangedState(api::BluetoothAdapter& adapter,
|
||||
api::BluetoothDevice& adapter_device,
|
||||
std::string name, bool enabled,
|
||||
api::BluetoothAdapter::ScanMode mode);
|
||||
|
||||
// Adds medium-related info to allow for adapter discovery to work.
|
||||
// This provides acccess to this medium from other mediums, when protocol
|
||||
// expects they should communicate.
|
||||
void RegisterBluetoothMedium(api::BluetoothClassicMedium& medium,
|
||||
api::BluetoothAdapter& medium_adapter);
|
||||
|
||||
// Updates callback info to allow for dispatch of discovery events.
|
||||
//
|
||||
// Invokes callback asynchronously when any changes happen to discoverable
|
||||
// devices, or if the defice is turned off, whether or not it is discoverable,
|
||||
// if it was ever reported as discoverable.
|
||||
//
|
||||
// This should be called when discoverable state changes.
|
||||
// with user-specified callback when discovery is enabled, and with default
|
||||
// (empty) callback otherwise.
|
||||
void UpdateBluetoothMedium(api::BluetoothClassicMedium& medium,
|
||||
BluetoothDiscoveryCallback callback);
|
||||
|
||||
// Removes medium-related info. This should correspond to device power off.
|
||||
void UnregisterBluetoothMedium(api::BluetoothClassicMedium& medium);
|
||||
|
||||
private:
|
||||
struct BluetoothMediumContext {
|
||||
BluetoothDiscoveryCallback callback;
|
||||
api::BluetoothAdapter* adapter = nullptr;
|
||||
// discovered device vs device name map.
|
||||
absl::flat_hash_map<api::BluetoothDevice*, std::string> devices;
|
||||
};
|
||||
|
||||
// This is a singleton object, for which destructor will never be called.
|
||||
// Constructor will be invoked once from Instance() static method.
|
||||
// Object is create in-place (with a placement new) to guarantee that
|
||||
// destructor is not scheduled for execution at exit.
|
||||
MediumEnvironment() = default;
|
||||
~MediumEnvironment() = default;
|
||||
|
||||
void OnDeviceStateChanged(BluetoothMediumContext& info,
|
||||
api::BluetoothDevice& device,
|
||||
const std::string& name,
|
||||
api::BluetoothAdapter::ScanMode mode, bool enabled);
|
||||
void RunOnMediumEnvironmentThread(std::function<void()> runnable);
|
||||
|
||||
std::atomic_bool enabled_ = true;
|
||||
std::atomic_int job_count_ = 0;
|
||||
std::atomic_bool enable_notifications_ = false;
|
||||
SingleThreadExecutor executor_;
|
||||
|
||||
// The following data members are accessed in the context of a private
|
||||
// executor_ thread.
|
||||
absl::flat_hash_map<api::BluetoothAdapter*, api::BluetoothDevice*>
|
||||
bluetooth_adapters_;
|
||||
absl::flat_hash_map<api::BluetoothClassicMedium*, BluetoothMediumContext>
|
||||
bluetooth_mediums_;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_MEDIUM_ENVIRONMENT_H_
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_OUTPUT_STREAM_H_
|
||||
#define PLATFORM_V2_BASE_OUTPUT_STREAM_H_
|
||||
|
||||
#include "platform_v2/base/byte_array.h"
|
||||
#include "platform_v2/base/exception.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// An OutputStream represents an output stream of bytes.
|
||||
//
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html
|
||||
class OutputStream {
|
||||
public:
|
||||
virtual ~OutputStream() = default;
|
||||
|
||||
virtual Exception Write(const ByteArray& data) = 0; // throws Exception::kIo
|
||||
virtual Exception Flush() = 0; // throws Exception::kIo
|
||||
virtual Exception Close() = 0; // throws Exception::kIo
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_OUTPUT_STREAM_H_
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform_v2/base/prng.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "absl/time/clock.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
#define UNSIGNED_INT_BITMASK (std::numeric_limits<unsigned int>::max())
|
||||
|
||||
Prng::Prng() {
|
||||
// absl::GetCurrentTimeNanos() returns 64 bits, but srand() wants an unsigned
|
||||
// int, so we may have to lose some of those 64 bits.
|
||||
//
|
||||
// The lower bits of the current-time-in-nanos are likely to have more entropy
|
||||
// than the upper bits, so choose the former.
|
||||
srand(static_cast<unsigned int>(absl::GetCurrentTimeNanos() &
|
||||
UNSIGNED_INT_BITMASK));
|
||||
}
|
||||
|
||||
Prng::~Prng() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
#define RANDOM_BYTE (rand() & 0x0FF) // NOLINT
|
||||
|
||||
std::int32_t Prng::NextInt32() {
|
||||
return (static_cast<std::int32_t>(RANDOM_BYTE) << 24) |
|
||||
(static_cast<std::int32_t>(RANDOM_BYTE) << 16) |
|
||||
(static_cast<std::int32_t>(RANDOM_BYTE) << 8) |
|
||||
(static_cast<std::int32_t>(RANDOM_BYTE));
|
||||
}
|
||||
|
||||
std::uint32_t Prng::NextUint32() {
|
||||
return static_cast<std::uint32_t>(NextInt32());
|
||||
}
|
||||
|
||||
std::int64_t Prng::NextInt64() {
|
||||
return (static_cast<std::int64_t>(NextInt32()) << 32) |
|
||||
(static_cast<std::int64_t>(NextInt32()));
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_PRNG_H_
|
||||
#define PLATFORM_V2_BASE_PRNG_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// A (non-cryptographic) pseudo-random number generator.
|
||||
class Prng {
|
||||
public:
|
||||
Prng();
|
||||
~Prng();
|
||||
|
||||
std::int32_t NextInt32();
|
||||
std::uint32_t NextUint32();
|
||||
std::int64_t NextInt64();
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_PRNG_H_
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform_v2/base/prng.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
TEST(PrngTest, NextInt32) {
|
||||
std::int32_t i = Prng().NextInt32();
|
||||
EXPECT_LE(i, std::numeric_limits<std::int32_t>::max());
|
||||
EXPECT_GE(i, std::numeric_limits<std::int32_t>::min());
|
||||
}
|
||||
|
||||
TEST(PrngTest, NextUInt32) {
|
||||
std::uint32_t i = Prng().NextUint32();
|
||||
EXPECT_LE(i, std::numeric_limits<std::uint32_t>::max());
|
||||
EXPECT_GE(i, std::numeric_limits<std::uint32_t>::min());
|
||||
}
|
||||
|
||||
TEST(PrngTest, NextInt64) {
|
||||
std::int64_t i = Prng().NextInt64();
|
||||
EXPECT_LE(i, std::numeric_limits<std::int64_t>::max());
|
||||
EXPECT_GE(i, std::numeric_limits<std::int64_t>::min());
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_RUNNABLE_H_
|
||||
#define PLATFORM_V2_BASE_RUNNABLE_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// The Runnable is an object intended to be executed by a thread.
|
||||
// It must be invokable without arguments. It must return void.
|
||||
//
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html
|
||||
|
||||
using Runnable = std::function<void()>;
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_RUNNABLE_H_
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_V2_BASE_SOCKET_H_
|
||||
#define PLATFORM_V2_BASE_SOCKET_H_
|
||||
|
||||
#include "platform_v2/base/input_stream.h"
|
||||
#include "platform_v2/base/output_stream.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
// A socket is an endpoint for communication between two machines.
|
||||
//
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html
|
||||
class Socket {
|
||||
public:
|
||||
virtual ~Socket() = default;
|
||||
|
||||
virtual InputStream& GetInputStream() = 0;
|
||||
virtual OutputStream& GetOutputStream() = 0;
|
||||
virtual void Close() = 0;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_V2_BASE_SOCKET_H_
|
||||
Reference in New Issue
Block a user