blob: 70e88638b004202199947d93a4b99f148e8ca5bf [file] [log] [blame]
Alexei Frolovf93cb262021-07-14 16:05:15 -07001// Copyright 2021 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#include "pw_transfer_private/chunk.h"
16
17#include "pw_protobuf/decoder.h"
18#include "pw_transfer/transfer.pwpb.h"
19
20namespace pw::transfer::internal {
21
22namespace ProtoChunk = transfer::Chunk;
23
24Status DecodeChunk(ConstByteSpan message, Chunk& chunk) {
25 protobuf::Decoder decoder(message);
26 Status status;
27 uint32_t value;
28
29 chunk = {};
30
31 while ((status = decoder.Next()).ok()) {
32 ProtoChunk::Fields field =
33 static_cast<ProtoChunk::Fields>(decoder.FieldNumber());
34
35 switch (field) {
36 case ProtoChunk::Fields::TRANSFER_ID:
37 PW_TRY(decoder.ReadUint32(&chunk.transfer_id));
38 break;
39
40 case ProtoChunk::Fields::PENDING_BYTES:
41 PW_TRY(decoder.ReadUint32(&value));
42 chunk.pending_bytes = value;
43 break;
44
45 case ProtoChunk::Fields::MAX_CHUNK_SIZE_BYTES:
46 PW_TRY(decoder.ReadUint32(&value));
47 chunk.max_chunk_size_bytes = value;
48 break;
49
50 case ProtoChunk::Fields::MIN_DELAY_MICROSECONDS:
51 PW_TRY(decoder.ReadUint32(&value));
52 chunk.min_delay_microseconds = value;
53 break;
54
55 case ProtoChunk::Fields::OFFSET:
56 PW_TRY(decoder.ReadUint32(&chunk.offset));
57 break;
58
59 case ProtoChunk::Fields::DATA:
60 PW_TRY(decoder.ReadBytes(&chunk.data));
61 break;
62
63 case ProtoChunk::Fields::REMAINING_BYTES: {
64 uint64_t remaining;
65 PW_TRY(decoder.ReadUint64(&remaining));
66 chunk.remaining_bytes = remaining;
67 break;
68 }
69
70 case ProtoChunk::Fields::STATUS:
71 PW_TRY(decoder.ReadUint32(&value));
72 chunk.status = static_cast<Status::Code>(value);
73 break;
74 }
75 }
76
77 return status.IsOutOfRange() ? OkStatus() : status;
78}
79
80Result<ConstByteSpan> EncodeChunk(const Chunk& chunk, ByteSpan buffer) {
Armando Montanez9f3708c2021-08-02 14:37:36 -070081 ProtoChunk::MemoryEncoder encoder(buffer);
Alexei Frolovf93cb262021-07-14 16:05:15 -070082
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000083 encoder.WriteTransferId(chunk.transfer_id)
84 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolovf93cb262021-07-14 16:05:15 -070085
86 if (chunk.pending_bytes.has_value()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000087 encoder.WritePendingBytes(chunk.pending_bytes.value())
88 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolovf93cb262021-07-14 16:05:15 -070089 }
90 if (chunk.max_chunk_size_bytes.has_value()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000091 encoder.WriteMaxChunkSizeBytes(chunk.max_chunk_size_bytes.value())
92 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolovf93cb262021-07-14 16:05:15 -070093 }
94 if (chunk.min_delay_microseconds.has_value()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000095 encoder.WriteMinDelayMicroseconds(chunk.min_delay_microseconds.value())
96 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolovf93cb262021-07-14 16:05:15 -070097 }
98 if (chunk.offset != 0) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000099 encoder.WriteOffset(chunk.offset)
100 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolovf93cb262021-07-14 16:05:15 -0700101 }
102 if (!chunk.data.empty()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000103 encoder.WriteData(chunk.data)
104 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolovf93cb262021-07-14 16:05:15 -0700105 }
106 if (chunk.remaining_bytes.has_value()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000107 encoder.WriteRemainingBytes(chunk.remaining_bytes.value())
108 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolovf93cb262021-07-14 16:05:15 -0700109 }
110 if (chunk.status.has_value()) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +0000111 encoder.WriteStatus(chunk.status.value().code())
112 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
Alexei Frolovf93cb262021-07-14 16:05:15 -0700113 }
114
115 PW_TRY(encoder.status());
116 return ConstByteSpan(encoder);
117}
118
119} // namespace pw::transfer::internal