blob: e09712518245ec22f5221ba11949ca52133f6e2e [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/fidl/llcpp/wire_coding_traits.h>
namespace fidl::internal {
void WireDecodeUnknownEnvelope(WireDecoder* decoder, WirePosition position) {
const fidl_envelope_v2_t* envelope = position.As<fidl_envelope_v2_t>();
if (envelope->flags == 0) {
if (envelope->num_bytes % FIDL_ALIGNMENT != 0) {
decoder->SetError(kCodingErrorInvalidNumBytesSpecifiedInEnvelope);
return;
}
WirePosition new_position;
if (!decoder->Alloc(envelope->num_bytes, &new_position)) {
return;
}
} else if (envelope->flags != FIDL_ENVELOPE_FLAGS_INLINING_MASK) {
decoder->SetError(kCodingErrorInvalidInlineBit);
return;
}
decoder->CloseNextNHandles(envelope->num_handles);
}
fitx::result<fidl::Error, WireEncoder::Result> WireEncode(
size_t inline_size, TopLevelEncodeFn encode_fn, const CodingConfig* coding_config, void* value,
zx_channel_iovec_t* iovecs, size_t iovec_capacity, fidl_handle_t* handles,
fidl_handle_metadata_t* handle_metadata, size_t handle_capacity, uint8_t* backing_buffer,
size_t backing_buffer_capacity) {
if (unlikely(value == nullptr)) {
return fitx::error(fidl::Error::DecodeError(ZX_ERR_INVALID_ARGS, kCodingErrorNullIovecBuffer));
}
if (unlikely(iovecs == nullptr)) {
return fitx::error(fidl::Error::DecodeError(ZX_ERR_INVALID_ARGS, kCodingErrorNullIovecBuffer));
}
if (unlikely(handle_capacity > 0 && handles == nullptr)) {
return fitx::error(
fidl::Error::DecodeError(ZX_ERR_INVALID_ARGS, kCodingErrorNullHandleBufferButNonzeroCount));
}
if (unlikely(backing_buffer == nullptr)) {
return fitx::error(fidl::Error::DecodeError(ZX_ERR_INVALID_ARGS, kCodingErrorNullByteBuffer));
}
WireEncoder encoder(coding_config, iovecs, iovec_capacity, handles, handle_metadata,
handle_capacity, backing_buffer, backing_buffer_capacity);
WirePosition position;
if (likely(encoder.Alloc(inline_size, &position))) {
encode_fn(&encoder, value, position);
}
return encoder.Finish();
}
fidl::Status WireDecode(size_t inline_size, TopLevelDecodeFn decode_fn,
const CodingConfig* coding_config, uint8_t* bytes, size_t num_bytes,
fidl_handle_t* handles, fidl_handle_metadata_t* handle_metadata,
size_t num_handles) {
if (unlikely(bytes == nullptr)) {
return fidl::Status::DecodeError(ZX_ERR_INVALID_ARGS, kCodingErrorNullByteBuffer);
}
if (unlikely(num_handles > 0 && handles == nullptr)) {
return fidl::Status::DecodeError(ZX_ERR_INVALID_ARGS,
kCodingErrorNullHandleBufferButNonzeroCount);
}
WireDecoder decoder(coding_config, bytes, num_bytes, handles, handle_metadata, num_handles);
WirePosition position;
if (likely(decoder.Alloc(inline_size, &position))) {
decode_fn(&decoder, position);
}
if (unlikely(decoder.CurrentLength() < num_bytes)) {
decoder.SetError(kCodingErrorNotAllBytesConsumed);
}
if (unlikely(decoder.CurrentHandleCount() < num_handles)) {
decoder.SetError(kCodingErrorNotAllHandlesConsumed);
}
return decoder.Finish();
}
} // namespace fidl::internal