[message] add new flavors of Read/Write/Append/Prepend methods (#5604)

This commit adds new helper methods in `Message` class. It adds new
template methods to allow an object (of any type) to be read from or
written/appended/prepended to the message. The `Read<ObjectType>()`
method returns a parse `otError` if there are not enough bytes
remaining in the message to read the entire object.

The template methods are used in other core modules which help
simplify the code (there is no need to specify the template type since
it can be deduced by the complier from the passed-in argument). Also
since the template methods directly use the `sizeof` the object type,
they help reduce the chance of incorrect use (using incorrect
read/write length when calling the method).

This commit also updates and renames the methods which read/write raw
bytes from/to the message to `ReadBytes()`/`WriteBytes()`. The order
of parameters in these methods are changed to follow the common
pattern used by other modules and the OT public APIs (i.e., the
pointer to the buffer is given first, followed by its length).
diff --git a/src/core/net/icmp6.cpp b/src/core/net/icmp6.cpp
index c10c506..a6736df 100644
--- a/src/core/net/icmp6.cpp
+++ b/src/core/net/icmp6.cpp
@@ -76,7 +76,7 @@
     icmpHeader.SetId(aIdentifier);
     icmpHeader.SetSequence(mEchoSequence++);
 
-    SuccessOrExit(error = aMessage.Prepend(&icmpHeader, sizeof(icmpHeader)));
+    SuccessOrExit(error = aMessage.Prepend(icmpHeader));
     aMessage.SetOffset(0);
     SuccessOrExit(error = Get<Ip6>().SendDatagram(aMessage, messageInfoLocal, kProtoIcmp6));
 
@@ -98,15 +98,11 @@
     ot::Ip6::Header   ip6Header;
     Message::Settings settings(Message::kWithLinkSecurity, Message::kPriorityNet);
 
-    VerifyOrExit(aMessage.GetLength() >= sizeof(ip6Header), error = OT_ERROR_INVALID_ARGS);
-
-    aMessage.Read(0, sizeof(ip6Header), &ip6Header);
+    SuccessOrExit(error = aMessage.Read(0, ip6Header));
 
     if (ip6Header.GetNextHeader() == kProtoIcmp6)
     {
-        VerifyOrExit(aMessage.GetLength() >= (sizeof(ip6Header) + sizeof(icmp6Header)), OT_NOOP);
-
-        aMessage.Read(sizeof(ip6Header), sizeof(icmp6Header), &icmp6Header);
+        SuccessOrExit(aMessage.Read(sizeof(ip6Header), icmp6Header));
         VerifyOrExit(!icmp6Header.IsError(), OT_NOOP);
     }
 
@@ -115,12 +111,12 @@
     VerifyOrExit((message = Get<Ip6>().NewMessage(0, settings)) != nullptr, error = OT_ERROR_NO_BUFS);
     SuccessOrExit(error = message->SetLength(sizeof(icmp6Header) + sizeof(ip6Header)));
 
-    message->Write(sizeof(icmp6Header), sizeof(ip6Header), &ip6Header);
+    message->Write(sizeof(icmp6Header), ip6Header);
 
     icmp6Header.Clear();
     icmp6Header.SetType(aType);
     icmp6Header.SetCode(aCode);
-    message->Write(0, sizeof(icmp6Header), &icmp6Header);
+    message->Write(0, icmp6Header);
 
     SuccessOrExit(error = Get<Ip6>().SendDatagram(*message, messageInfoLocal, kProtoIcmp6));
 
@@ -136,8 +132,7 @@
     otError error = OT_ERROR_NONE;
     Header  icmp6Header;
 
-    VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(icmp6Header), &icmp6Header) == sizeof(icmp6Header),
-                 error = OT_ERROR_PARSE);
+    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), icmp6Header));
 
     SuccessOrExit(error = Checksum::VerifyMessageChecksum(aMessage, aMessageInfo, kProtoIcmp6));
 
@@ -205,7 +200,7 @@
     payloadLength = aRequestMessage.GetLength() - aRequestMessage.GetOffset() - Header::kDataFieldOffset;
     SuccessOrExit(error = replyMessage->SetLength(Header::kDataFieldOffset + payloadLength));
 
-    replyMessage->Write(0, Header::kDataFieldOffset, &icmp6Header);
+    replyMessage->WriteBytes(0, &icmp6Header, Header::kDataFieldOffset);
     aRequestMessage.CopyTo(aRequestMessage.GetOffset() + Header::kDataFieldOffset, Header::kDataFieldOffset,
                            payloadLength, *replyMessage);
 
@@ -218,7 +213,7 @@
 
     SuccessOrExit(error = Get<Ip6>().SendDatagram(*replyMessage, replyMessageInfo, kProtoIcmp6));
 
-    replyMessage->Read(replyMessage->GetOffset(), sizeof(icmp6Header), &icmp6Header);
+    IgnoreError(replyMessage->Read(replyMessage->GetOffset(), icmp6Header));
     otLogInfoIcmp("Sent Echo Reply (seq = %d)", icmp6Header.GetSequence());
 
 exit: