xref: /aosp_15_r20/external/cronet/base/fuchsia/mem_buffer_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/fuchsia/mem_buffer_util.h"
6 
7 #include <lib/fdio/io.h>
8 #include <lib/zx/vmo.h>
9 
10 #include <string>
11 #include <string_view>
12 #include <utility>
13 
14 #include "base/files/file.h"
15 #include "base/fuchsia/fuchsia_logging.h"
16 #include "base/numerics/safe_conversions.h"
17 #include "base/strings/utf_string_conversions.h"
18 
19 namespace base {
20 
ReadUTF8FromVMOAsUTF16(const fuchsia::mem::Buffer & buffer)21 std::optional<std::u16string> ReadUTF8FromVMOAsUTF16(
22     const fuchsia::mem::Buffer& buffer) {
23   std::optional<std::string> output_utf8 = StringFromMemBuffer(buffer);
24   if (!output_utf8)
25     return std::nullopt;
26   std::u16string output;
27   return UTF8ToUTF16(&output_utf8->front(), output_utf8->size(), &output)
28              ? std::optional<std::u16string>(std::move(output))
29              : std::nullopt;
30 }
31 
VmoFromString(std::string_view data,std::string_view name)32 zx::vmo VmoFromString(std::string_view data, std::string_view name) {
33   zx::vmo vmo;
34 
35   // The `ZX_PROP_VMO_CONTENT_SIZE` property is automatically set on VMO
36   // creation.
37   zx_status_t status = zx::vmo::create(data.size(), 0, &vmo);
38   ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create";
39   status = vmo.set_property(ZX_PROP_NAME, name.data(), name.size());
40   ZX_DCHECK(status == ZX_OK, status);
41   if (data.size() > 0) {
42     status = vmo.write(data.data(), 0, data.size());
43     ZX_CHECK(status == ZX_OK, status) << "zx_vmo_write";
44   }
45   return vmo;
46 }
47 
MemBufferFromString(std::string_view data,std::string_view name)48 fuchsia::mem::Buffer MemBufferFromString(std::string_view data,
49                                          std::string_view name) {
50   fuchsia::mem::Buffer buffer;
51   buffer.vmo = VmoFromString(data, name);
52   buffer.size = data.size();
53   return buffer;
54 }
55 
MemBufferFromString16(std::u16string_view data,std::string_view name)56 fuchsia::mem::Buffer MemBufferFromString16(std::u16string_view data,
57                                            std::string_view name) {
58   return MemBufferFromString(
59       std::string_view(reinterpret_cast<const char*>(data.data()),
60                        data.size() * sizeof(char16_t)),
61       name);
62 }
63 
StringFromVmo(const zx::vmo & vmo)64 std::optional<std::string> StringFromVmo(const zx::vmo& vmo) {
65   std::string result;
66 
67   size_t size;
68   zx_status_t status = vmo.get_prop_content_size(&size);
69   if (status != ZX_OK) {
70     ZX_LOG(ERROR, status) << "zx::vmo::get_prop_content_size";
71     return std::nullopt;
72   }
73 
74   if (size == 0)
75     return result;
76 
77   result.resize(size);
78   status = vmo.read(&result[0], 0, size);
79   if (status == ZX_OK)
80     return result;
81 
82   ZX_LOG(ERROR, status) << "zx_vmo_read";
83   return std::nullopt;
84 }
85 
StringFromMemBuffer(const fuchsia::mem::Buffer & buffer)86 std::optional<std::string> StringFromMemBuffer(
87     const fuchsia::mem::Buffer& buffer) {
88   std::string result;
89 
90   if (buffer.size == 0)
91     return result;
92 
93   result.resize(buffer.size);
94   zx_status_t status = buffer.vmo.read(&result[0], 0, buffer.size);
95   if (status == ZX_OK)
96     return result;
97 
98   ZX_LOG(ERROR, status) << "zx_vmo_read";
99   return std::nullopt;
100 }
101 
StringFromMemData(const fuchsia::mem::Data & data)102 std::optional<std::string> StringFromMemData(const fuchsia::mem::Data& data) {
103   switch (data.Which()) {
104     case fuchsia::mem::Data::kBytes: {
105       const std::vector<uint8_t>& bytes = data.bytes();
106       return std::string(bytes.begin(), bytes.end());
107     }
108     case fuchsia::mem::Data::kBuffer:
109       return StringFromMemBuffer(data.buffer());
110     case fuchsia::mem::Data::kUnknown:
111     case fuchsia::mem::Data::Invalid:
112       // TODO(fxbug.dev/66155): Determine whether to use a default case instead.
113       break;
114   }
115 
116   return std::nullopt;
117 }
118 
MemBufferFromFile(File file)119 fuchsia::mem::Buffer MemBufferFromFile(File file) {
120   if (!file.IsValid())
121     return {};
122 
123   zx::vmo vmo;
124   zx_status_t status =
125       fdio_get_vmo_copy(file.GetPlatformFile(), vmo.reset_and_get_address());
126   if (status != ZX_OK) {
127     ZX_LOG(ERROR, status) << "fdio_get_vmo_copy";
128     return {};
129   }
130 
131   fuchsia::mem::Buffer output;
132   output.vmo = std::move(vmo);
133   output.size = checked_cast<uint64_t>(file.GetLength());
134   return output;
135 }
136 
CloneBuffer(const fuchsia::mem::Buffer & buffer,std::string_view name)137 fuchsia::mem::Buffer CloneBuffer(const fuchsia::mem::Buffer& buffer,
138                                  std::string_view name) {
139   fuchsia::mem::Buffer output;
140   output.size = buffer.size;
141   zx_status_t status = buffer.vmo.create_child(
142       ZX_VMO_CHILD_SNAPSHOT_AT_LEAST_ON_WRITE, 0, buffer.size, &output.vmo);
143   ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create_child";
144 
145   status = output.vmo.set_property(ZX_PROP_NAME, name.data(), name.size());
146   ZX_DCHECK(status == ZX_OK, status);
147 
148   return output;
149 }
150 
151 }  // namespace base
152