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