• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2025 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 #pragma once
15 
16 #include "pw_bytes/alignment.h"
17 #include "pw_span/internal/config.h"
18 #include "pw_span/span.h"
19 
20 namespace pw {
21 namespace internal {
22 
23 template <class ResultT, size_t kSourceExtentBytes>
24 using SpanFromBytes = span<ResultT,
25                            (kSourceExtentBytes == dynamic_extent
26                                 ? dynamic_extent
27                                 : kSourceExtentBytes / sizeof(ResultT))>;
28 
29 }  // namespace internal
30 
31 /// @defgroup pw_span_cast
32 /// @{
33 
34 /// Casts a `pw::span<std::byte>` (`ByteSpan`) to a span of a different type.
35 ///
36 /// This function is only safe to use if the underlying data is actually of the
37 /// specified type. You cannot safely use this function to reinterpret e.g. a
38 /// raw byte array from `malloc()` as a span of integers.
39 ///
40 /// This function is essentially the inverse of `pw::as_writable_bytes`.
41 ///
42 /// If `kSourceExtentBytes` is `dynamic_extent`, the returned span also has a
43 /// dynamic extent.  Otherwise, the returned span has a static extent of
44 /// `kSourceExtentBytes / sizeof(ResultT)`.
45 ///
46 /// @tparam  ResultT             The type of the returned span.
47 ///                              Must be one byte to avoid misuse and violation
48 ///                              of the strict aliasing rule. This restriction
49 ///                              might be lifted in the future.
50 /// @tparam  kSourceExtentBytes  The extent of the source byte span. This is
51 ///                              normally inferred and need not be explicitly
52 ///                              provided.
53 template <class ResultT, size_t kSourceExtentBytes>
span_cast(span<std::byte,kSourceExtentBytes> bytes)54 internal::SpanFromBytes<ResultT, kSourceExtentBytes> span_cast(
55     span<std::byte, kSourceExtentBytes> bytes) {
56   static_assert(sizeof(ResultT) == 1);
57 
58   ResultT* const ptr = reinterpret_cast<ResultT*>(bytes.data());
59   const size_t count = bytes.size() / sizeof(ResultT);
60 
61   auto result =
62       internal::SpanFromBytes<ResultT, kSourceExtentBytes>{ptr, count};
63 
64   _PW_SPAN_ASSERT(IsAlignedAs<ResultT>(result.data()));
65   _PW_SPAN_ASSERT(result.size_bytes() == bytes.size_bytes());
66 
67   return result;
68 }
69 
70 // TODO: https://pwbug.dev/396493663 - Doxygen thinks this is the same function
71 // as the non-const version above, and merges the docs together.
72 
73 /// Casts a `pw::span<const std::byte>` (`ConstByteSpan`) to a span of a
74 /// different const type.
75 ///
76 /// This function is only safe to use if the underlying data is actually of the
77 /// specified type. You cannot safely use this function to reinterpret e.g. a
78 /// raw byte array from `malloc()` as a span of integers.
79 ///
80 /// This function is essentially the inverse of `pw::as_bytes`.
81 ///
82 /// If `kSourceExtentBytes` is `dynamic_extent`, the returned span also has a
83 /// dynamic extent.  Otherwise, the returned span has a static extent of
84 /// `kSourceExtentBytes / sizeof(ResultT)`.
85 ///
86 /// @tparam  ResultT             The type of the returned span.
87 ///                              Must be one byte to avoid misuse and violation
88 ///                              of the strict aliasing rule. This restriction
89 ///                              might be lifted in the future.
90 /// @tparam  kSourceExtentBytes  The extent of the source byte span. This is
91 ///                              normally inferred and need not be explicitly
92 ///                              provided.
93 template <class ResultT, size_t kSourceExtentBytes>
span_cast(span<const std::byte,kSourceExtentBytes> bytes)94 internal::SpanFromBytes<const ResultT, kSourceExtentBytes> span_cast(
95     span<const std::byte, kSourceExtentBytes> bytes) {
96   static_assert(sizeof(ResultT) == 1);
97 
98   const ResultT* const ptr = reinterpret_cast<const ResultT*>(bytes.data());
99   const size_t count = bytes.size() / sizeof(ResultT);
100 
101   auto result =
102       internal::SpanFromBytes<const ResultT, kSourceExtentBytes>{ptr, count};
103 
104   _PW_SPAN_ASSERT(IsAlignedAs<const ResultT>(result.data()));
105   _PW_SPAN_ASSERT(result.size_bytes() == bytes.size_bytes());
106 
107   return result;
108 }
109 
110 /// @}
111 
112 }  // namespace pw
113