diff --git a/view.hpp b/view.hpp index 0857215a..84f2d603 100644 --- a/view.hpp +++ b/view.hpp @@ -806,6 +806,8 @@ namespace cruft { /// /// in contrast to 'extract' this will always copy the bytes out from the /// view, making the operation alignment safe. + /// + /// It is safe to use this on untrusted input. template < typename ValueT, typename WordT, @@ -828,6 +830,54 @@ namespace cruft { } + /////////////////////////////////////////////////////////////////////////// + template < + typename ValueT, + typename WordT, + typename = std::enable_if_t + > + view + write [[nodiscard]] (view const &dst, ValueT const &src) + { + static_assert (std::is_trivially_copyable_v); + + if (unlikely (sizeof (ValueT) > dst.size () * sizeof (WordT))) + throw std::runtime_error ("insufficient data for extraction"); + + memcpy (dst.data (), &src, sizeof (ValueT)); + return { + dst.begin () + sizeof (ValueT) / sizeof (WordT), + dst.end (), + }; + } + + + template < + typename ValueT, + typename WordT, + typename = std::enable_if_t + > + view + write [[nodiscard]] (view const &dst, cruft::view src) + { + static_assert (std::is_trivially_copyable_v); + + if (unlikely (src.size () * sizeof (ValueT) > dst.size () * sizeof (WordT))) + throw std::runtime_error ("insufficient data for extraction"); + + memcpy ( + dst.data (), + src.data (), + src.size () * sizeof (ValueT) + ); + + return { + dst.begin () + (sizeof (ValueT) / sizeof (WordT)) * src.size (), + dst.end (), + }; + } + + /////////////////////////////////////////////////////////////////////////// /// Tests whether an iterator falls within a given view. template