dsp: base: Implement decode_multipart_receive_req() in terms of msgbuf

Also rework related tests so we can avoid the casting the struct
over the buffers. This is motivated by an impending patch that drops
__attribute__((packed)) from the struct definition.

Change-Id: I21386e12ea65577920237fd28ea1fd340c749f42
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
diff --git a/src/dsp/base.c b/src/dsp/base.c
index ee2cd04..7609f25 100644
--- a/src/dsp/base.c
+++ b/src/dsp/base.c
@@ -533,49 +533,52 @@
 				 uint32_t *section_offset,
 				 uint32_t *section_length)
 {
+	PLDM_MSGBUF_DEFINE_P(buf);
+	int rc;
+
 	if (msg == NULL || pldm_type == NULL || transfer_opflag == NULL ||
 	    transfer_ctx == NULL || transfer_handle == NULL ||
 	    section_offset == NULL || section_length == NULL) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	if (payload_length != PLDM_MULTIPART_RECEIVE_REQ_BYTES) {
-		return PLDM_ERROR_INVALID_LENGTH;
+	rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
+				    msg->payload, payload_length);
+	if (rc) {
+		return pldm_xlate_errno(rc);
 	}
 
-	struct pldm_multipart_receive_req *request =
-		(struct pldm_multipart_receive_req *)msg->payload;
+	pldm_msgbuf_extract_p(buf, pldm_type);
+	pldm_msgbuf_extract_p(buf, transfer_opflag);
+	pldm_msgbuf_extract_p(buf, transfer_ctx);
+	pldm_msgbuf_extract_p(buf, transfer_handle);
+	pldm_msgbuf_extract_p(buf, section_offset);
+	pldm_msgbuf_extract_p(buf, section_length);
 
-	if (request->pldm_type != PLDM_BASE &&
-	    request->pldm_type != PLDM_FILE) {
+	rc = pldm_msgbuf_complete_consumed(buf);
+	if (rc) {
+		return pldm_xlate_errno(rc);
+	}
+
+	if (*pldm_type != PLDM_BASE && *pldm_type != PLDM_FILE) {
 		return PLDM_ERROR_INVALID_PLDM_TYPE;
 	}
 
 	// Any enum value above PLDM_XFER_CURRENT_PART is invalid.
-	if (request->transfer_opflag > PLDM_XFER_CURRENT_PART) {
+	if (*transfer_opflag > PLDM_XFER_CURRENT_PART) {
 		return PLDM_ERROR_UNEXPECTED_TRANSFER_FLAG_OPERATION;
 	}
 
 	// A section offset of 0 is only valid on FIRST_PART or COMPLETE Xfers.
-	uint32_t sec_offset = le32toh(request->section_offset);
-	if (sec_offset == 0 &&
-	    (request->transfer_opflag != PLDM_XFER_FIRST_PART &&
-	     request->transfer_opflag != PLDM_XFER_COMPLETE)) {
+	if (*section_offset == 0 && (*transfer_opflag != PLDM_XFER_FIRST_PART &&
+				     *transfer_opflag != PLDM_XFER_COMPLETE)) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	uint32_t handle = le32toh(request->transfer_handle);
-	if (handle == 0 && request->transfer_opflag != PLDM_XFER_COMPLETE) {
+	if (*transfer_handle == 0 && *transfer_opflag != PLDM_XFER_COMPLETE) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	*pldm_type = request->pldm_type;
-	*transfer_opflag = request->transfer_opflag;
-	*transfer_ctx = request->transfer_ctx;
-	*transfer_handle = handle;
-	*section_offset = sec_offset;
-	*section_length = le32toh(request->section_length);
-
 	return PLDM_SUCCESS;
 }
 
diff --git a/tests/dsp/base.cpp b/tests/dsp/base.cpp
index 0c10ff7..d073ac4 100644
--- a/tests/dsp/base.cpp
+++ b/tests/dsp/base.cpp
@@ -540,7 +540,7 @@
     EXPECT_EQ(tid, 1);
 }
 
-TEST(MultipartReceive, testDecodeRequestPass)
+TEST(DecodeMultipartReceiveResponse, testDecodeRequestPass)
 {
     constexpr uint8_t kPldmType = PLDM_BASE;
     constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
@@ -548,36 +548,35 @@
     constexpr uint32_t kTransferHandle = 0x10;
     constexpr uint32_t kSectionOffset = 0x0;
     constexpr uint32_t kSectionLength = 0x10;
-    uint8_t pldm_type = 0x0;
-    uint8_t flag = PLDM_GET_FIRSTPART;
+
+    PLDM_MSG_DEFINE_P(msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    PLDM_MSGBUF_DEFINE_P(buf);
+    int rc;
+
+    // Header values don't matter for this test.
+    rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
+                                msg->payload, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    ASSERT_EQ(rc, 0);
+    pldm_msgbuf_insert_uint8(buf, kPldmType);
+    pldm_msgbuf_insert_uint8(buf, kFlag);
+    pldm_msgbuf_insert_uint32(buf, kTransferCtx);
+    pldm_msgbuf_insert_uint32(buf, kTransferHandle);
+    pldm_msgbuf_insert_uint32(buf, kSectionOffset);
+    pldm_msgbuf_insert_uint32(buf, kSectionLength);
+    rc = pldm_msgbuf_complete(buf);
+    ASSERT_EQ(rc, 0);
+
+    uint8_t pldm_type;
+    uint8_t flag;
     uint32_t transfer_ctx;
     uint32_t transfer_handle;
     uint32_t section_offset;
     uint32_t section_length;
-
-    // Header values don't matter for this test.
-    pldm_msg_hdr hdr{};
-    // Assign values to the packet struct and memcpy to ensure correct byte
-    // ordering.
-    pldm_multipart_receive_req req_pkt = {
-        .pldm_type = kPldmType,
-        .transfer_opflag = kFlag,
-        .transfer_ctx = kTransferCtx,
-        .transfer_handle = kTransferHandle,
-        .section_offset = kSectionOffset,
-        .section_length = kSectionLength,
-    };
-    std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
-    std::memcpy(req.data(), &hdr, sizeof(hdr));
-    std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
-
-    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
-    int rc = decode_multipart_receive_req(
-        pldm_request, req.size() - hdrSize, &pldm_type, &flag, &transfer_ctx,
+    rc = decode_multipart_receive_req(
+        msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES, &pldm_type, &flag, &transfer_ctx,
         &transfer_handle, &section_offset, &section_length);
 
-    EXPECT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
     EXPECT_EQ(pldm_type, kPldmType);
     EXPECT_EQ(flag, kFlag);
     EXPECT_EQ(transfer_ctx, kTransferCtx);
@@ -586,17 +585,16 @@
     EXPECT_EQ(section_length, kSectionLength);
 }
 
-TEST(MultipartReceive, testDecodeRequestFailNullData)
+TEST(DecodeMultipartReceiveResponse, testDecodeRequestFailNullData)
 {
     EXPECT_EQ(decode_multipart_receive_req(NULL, 0, NULL, NULL, NULL, NULL,
                                            NULL, NULL),
               PLDM_ERROR_INVALID_DATA);
 }
 
-TEST(MultipartReceive, testDecodeRequestFailBadLength)
+TEST(DecodeMultipartReceiveResponse, testDecodeRequestFailBadLength)
 {
-    constexpr uint8_t kPldmType = PLDM_BASE;
-    constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
+    PLDM_MSG_DEFINE_P(msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES + 1);
     uint8_t pldm_type;
     uint8_t flag;
     uint32_t transfer_ctx;
@@ -604,133 +602,32 @@
     uint32_t section_offset;
     uint32_t section_length;
 
-    // Header values don't matter for this test.
-    pldm_msg_hdr hdr{};
-    // Assign values to the packet struct and memcpy to ensure correct byte
-    // ordering.
-    pldm_multipart_receive_req req_pkt{};
-    req_pkt.pldm_type = kPldmType;
-    req_pkt.transfer_opflag = kFlag;
-
-    std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
-    std::memcpy(req.data(), &hdr, sizeof(hdr));
-    std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
-
-    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
+    memset(msg, 0, PLDM_MSG_SIZE(PLDM_MULTIPART_RECEIVE_REQ_BYTES + 1));
     EXPECT_EQ(decode_multipart_receive_req(
-                  pldm_request, (req.size() - hdrSize) + 1, &pldm_type, &flag,
+                  msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES + 1, &pldm_type, &flag,
                   &transfer_ctx, &transfer_handle, &section_offset,
                   &section_length),
-              PLDM_ERROR_INVALID_LENGTH);
-}
-
-TEST(MultipartReceive, testDecodeRequestFailBadPldmType)
-{
-    constexpr uint8_t kPldmType = 0xff;
-    constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
-    uint8_t pldm_type;
-    uint8_t flag;
-    uint32_t transfer_ctx;
-    uint32_t transfer_handle;
-    uint32_t section_offset;
-    uint32_t section_length;
-
-    // Header values don't matter for this test.
-    pldm_msg_hdr hdr{};
-    // Assign values to the packet struct and memcpy to ensure correct byte
-    // ordering.
-    pldm_multipart_receive_req req_pkt{};
-    req_pkt.pldm_type = kPldmType;
-    req_pkt.transfer_opflag = kFlag;
-
-    std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
-    std::memcpy(req.data(), &hdr, sizeof(hdr));
-    std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
-
-    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
-    EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
-                                           &pldm_type, &flag, &transfer_ctx,
-                                           &transfer_handle, &section_offset,
-                                           &section_length),
-              PLDM_ERROR_INVALID_PLDM_TYPE);
-}
-
-TEST(MultipartReceive, testDecodeRequestFailBadTransferFlag)
-{
-    constexpr uint8_t kPldmType = PLDM_BASE;
-    constexpr uint8_t kFlag = PLDM_XFER_CURRENT_PART + 0x10;
-    uint8_t pldm_type;
-    uint8_t flag;
-    uint32_t transfer_ctx;
-    uint32_t transfer_handle;
-    uint32_t section_offset;
-    uint32_t section_length;
-
-    // Header values don't matter for this test.
-    pldm_msg_hdr hdr{};
-    // Assign values to the packet struct and memcpy to ensure correct byte
-    // ordering.
-    pldm_multipart_receive_req req_pkt{};
-    req_pkt.pldm_type = kPldmType;
-    req_pkt.transfer_opflag = kFlag;
-
-    std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
-    std::memcpy(req.data(), &hdr, sizeof(hdr));
-    std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
-
-    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
-    EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
-                                           &pldm_type, &flag, &transfer_ctx,
-                                           &transfer_handle, &section_offset,
-                                           &section_length),
-              PLDM_ERROR_UNEXPECTED_TRANSFER_FLAG_OPERATION);
-}
-
-TEST(MultipartReceive, testDecodeRequestFailBadOffset)
-{
-    constexpr uint8_t kPldmType = PLDM_BASE;
-    constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
-    constexpr uint32_t kTransferHandle = 0x01;
-    constexpr uint32_t kSectionOffset = 0x0;
-    uint8_t pldm_type;
-    uint8_t flag;
-    uint32_t transfer_ctx;
-    uint32_t transfer_handle;
-    uint32_t section_offset;
-    uint32_t section_length;
-
-    // Header values don't matter for this test.
-    pldm_msg_hdr hdr{};
-    // Assign values to the packet struct and memcpy to ensure correct byte
-    // ordering.
-    pldm_multipart_receive_req req_pkt{};
-    req_pkt.pldm_type = kPldmType;
-    req_pkt.transfer_opflag = kFlag;
-    req_pkt.transfer_handle = kTransferHandle;
-    req_pkt.section_offset = kSectionOffset;
-
-    std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
-    std::memcpy(req.data(), &hdr, sizeof(hdr));
-    std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
-
-    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
-    EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
-                                           &pldm_type, &flag, &transfer_ctx,
-                                           &transfer_handle, &section_offset,
-                                           &section_length),
               PLDM_ERROR_INVALID_DATA);
 }
 
-TEST(MultipartReceive, testDecodeRequestFailBadHandle)
+TEST(DecodeMultipartReceiveResponse, testDecodeRequestFailBadPldmType)
 {
-    constexpr uint8_t kPldmType = PLDM_BASE;
-    constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
-    constexpr uint32_t kSectionOffset = 0x100;
-    constexpr uint32_t kTransferHandle = 0x0;
+    constexpr uint8_t kPldmType = 0xff;
+    constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
+
+    PLDM_MSG_DEFINE_P(msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    PLDM_MSGBUF_DEFINE_P(buf);
+    int rc;
+
+    // Header values don't matter for this test.
+    rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
+                                msg->payload, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    ASSERT_EQ(rc, 0);
+    pldm_msgbuf_insert_uint8(buf, kPldmType);
+    pldm_msgbuf_insert_uint8(buf, kFlag);
+    rc = pldm_msgbuf_complete(buf);
+    ASSERT_EQ(rc, 0);
+
     uint8_t pldm_type;
     uint8_t flag;
     uint32_t transfer_ctx;
@@ -738,26 +635,116 @@
     uint32_t section_offset;
     uint32_t section_length;
 
+    EXPECT_EQ(decode_multipart_receive_req(
+                  msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES, &pldm_type, &flag,
+                  &transfer_ctx, &transfer_handle, &section_offset,
+                  &section_length),
+              PLDM_ERROR_INVALID_PLDM_TYPE);
+}
+
+TEST(DecodeMultipartReceiveResponse, testDecodeRequestFailBadTransferFlag)
+{
+    constexpr uint8_t kPldmType = PLDM_BASE;
+    constexpr uint8_t kFlag = PLDM_XFER_CURRENT_PART + 0x10;
+
+    PLDM_MSG_DEFINE_P(msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    PLDM_MSGBUF_DEFINE_P(buf);
+    int rc;
+
     // Header values don't matter for this test.
-    pldm_msg_hdr hdr{};
-    // Assign values to the packet struct and memcpy to ensure correct byte
-    // ordering.
-    pldm_multipart_receive_req req_pkt{};
-    req_pkt.pldm_type = kPldmType;
-    req_pkt.transfer_opflag = kFlag;
-    req_pkt.transfer_handle = kTransferHandle;
-    req_pkt.section_offset = kSectionOffset;
+    rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
+                                msg->payload, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    ASSERT_EQ(rc, 0);
+    pldm_msgbuf_insert_uint8(buf, kPldmType);
+    pldm_msgbuf_insert_uint8(buf, kFlag);
+    rc = pldm_msgbuf_complete(buf);
+    ASSERT_EQ(rc, 0);
 
-    std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
-    std::memcpy(req.data(), &hdr, sizeof(hdr));
-    std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
+    uint8_t pldm_type;
+    uint8_t flag;
+    uint32_t transfer_ctx;
+    uint32_t transfer_handle;
+    uint32_t section_offset;
+    uint32_t section_length;
 
-    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
-    EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
-                                           &pldm_type, &flag, &transfer_ctx,
-                                           &transfer_handle, &section_offset,
-                                           &section_length),
+    EXPECT_EQ(decode_multipart_receive_req(
+                  msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES, &pldm_type, &flag,
+                  &transfer_ctx, &transfer_handle, &section_offset,
+                  &section_length),
+              PLDM_ERROR_UNEXPECTED_TRANSFER_FLAG_OPERATION);
+}
+
+TEST(DecodeMultipartReceiveResponse, testDecodeRequestFailBadOffset)
+{
+    constexpr uint8_t kPldmType = PLDM_BASE;
+    constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
+    constexpr uint32_t kTransferCtx = 0x01;
+    constexpr uint32_t kTransferHandle = 0x01;
+    constexpr uint32_t kSectionOffset = 0x0;
+
+    PLDM_MSG_DEFINE_P(msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    PLDM_MSGBUF_DEFINE_P(buf);
+    int rc;
+
+    // Header values don't matter for this test.
+    rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
+                                msg->payload, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    ASSERT_EQ(rc, 0);
+    pldm_msgbuf_insert_uint8(buf, kPldmType);
+    pldm_msgbuf_insert_uint8(buf, kFlag);
+    pldm_msgbuf_insert_uint32(buf, kTransferCtx);
+    pldm_msgbuf_insert_uint32(buf, kTransferHandle);
+    pldm_msgbuf_insert_uint32(buf, kSectionOffset);
+    rc = pldm_msgbuf_complete(buf);
+    ASSERT_EQ(rc, 0);
+
+    uint8_t pldm_type;
+    uint8_t flag;
+    uint32_t transfer_ctx;
+    uint32_t transfer_handle;
+    uint32_t section_offset;
+    uint32_t section_length;
+    EXPECT_EQ(decode_multipart_receive_req(
+                  msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES, &pldm_type, &flag,
+                  &transfer_ctx, &transfer_handle, &section_offset,
+                  &section_length),
+              PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(DecodeMultipartReceiveResponse, testDecodeRequestFailBadHandle)
+{
+    constexpr uint8_t kPldmType = PLDM_BASE;
+    constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
+    constexpr uint32_t kTransferCtx = 0x01;
+    constexpr uint32_t kTransferHandle = 0x0;
+    constexpr uint32_t kSectionOffset = 0x100;
+
+    PLDM_MSG_DEFINE_P(msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    PLDM_MSGBUF_DEFINE_P(buf);
+    int rc;
+
+    // Header values don't matter for this test.
+    rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
+                                msg->payload, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+    ASSERT_EQ(rc, 0);
+    pldm_msgbuf_insert_uint8(buf, kPldmType);
+    pldm_msgbuf_insert_uint8(buf, kFlag);
+    pldm_msgbuf_insert_uint32(buf, kTransferCtx);
+    pldm_msgbuf_insert_uint32(buf, kTransferHandle);
+    pldm_msgbuf_insert_uint32(buf, kSectionOffset);
+    rc = pldm_msgbuf_complete(buf);
+    ASSERT_EQ(rc, 0);
+
+    uint8_t pldm_type;
+    uint8_t flag;
+    uint32_t transfer_ctx;
+    uint32_t transfer_handle;
+    uint32_t section_offset;
+    uint32_t section_length;
+    EXPECT_EQ(decode_multipart_receive_req(
+                  msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES, &pldm_type, &flag,
+                  &transfer_ctx, &transfer_handle, &section_offset,
+                  &section_length),
               PLDM_ERROR_INVALID_DATA);
 }
 
@@ -1636,4 +1623,4 @@
 
     EXPECT_EQ(rc, -EOVERFLOW);
 }
-#endif
\ No newline at end of file
+#endif