xref: /aosp_15_r20/external/cronet/base/json/values_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2019 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/json/values_util.h"
6 
7 #include <optional>
8 
9 #include "base/files/file_path.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/time/time.h"
12 #include "base/unguessable_token.h"
13 
14 // Warning: The Values involved could be stored on persistent storage like files
15 // on disks. Therefore, changes in implementation could lead to data corruption
16 // and must be done with caution.
17 
18 namespace base {
19 
20 namespace {
21 
22 // Helper to serialize/deserialize an UnguessableToken.
23 //
24 // It assumes a little-endian CPU, which is arguably a bug.
25 union UnguessableTokenRepresentation {
26   struct Field {
27     uint64_t high;
28     uint64_t low;
29   } field;
30 
31   uint8_t buffer[sizeof(Field)];
32 };
33 
34 }  // namespace
35 
Int64ToValue(int64_t integer)36 Value Int64ToValue(int64_t integer) {
37   return Value(NumberToString(integer));
38 }
39 
ValueToInt64(const Value * value)40 std::optional<int64_t> ValueToInt64(const Value* value) {
41   return value ? ValueToInt64(*value) : std::nullopt;
42 }
43 
ValueToInt64(const Value & value)44 std::optional<int64_t> ValueToInt64(const Value& value) {
45   if (!value.is_string())
46     return std::nullopt;
47 
48   int64_t integer;
49   if (!StringToInt64(value.GetString(), &integer))
50     return std::nullopt;
51 
52   return integer;
53 }
54 
TimeDeltaToValue(TimeDelta time_delta)55 Value TimeDeltaToValue(TimeDelta time_delta) {
56   return Int64ToValue(time_delta.InMicroseconds());
57 }
58 
ValueToTimeDelta(const Value * value)59 std::optional<TimeDelta> ValueToTimeDelta(const Value* value) {
60   return value ? ValueToTimeDelta(*value) : std::nullopt;
61 }
62 
ValueToTimeDelta(const Value & value)63 std::optional<TimeDelta> ValueToTimeDelta(const Value& value) {
64   std::optional<int64_t> integer = ValueToInt64(value);
65   if (!integer)
66     return std::nullopt;
67   return Microseconds(*integer);
68 }
69 
TimeToValue(Time time)70 Value TimeToValue(Time time) {
71   return TimeDeltaToValue(time.ToDeltaSinceWindowsEpoch());
72 }
73 
ValueToTime(const Value * value)74 std::optional<Time> ValueToTime(const Value* value) {
75   return value ? ValueToTime(*value) : std::nullopt;
76 }
77 
ValueToTime(const Value & value)78 std::optional<Time> ValueToTime(const Value& value) {
79   std::optional<TimeDelta> time_delta = ValueToTimeDelta(value);
80   if (!time_delta)
81     return std::nullopt;
82   return Time::FromDeltaSinceWindowsEpoch(*time_delta);
83 }
84 
FilePathToValue(FilePath file_path)85 Value FilePathToValue(FilePath file_path) {
86   return Value(file_path.AsUTF8Unsafe());
87 }
88 
ValueToFilePath(const Value * value)89 std::optional<FilePath> ValueToFilePath(const Value* value) {
90   return value ? ValueToFilePath(*value) : std::nullopt;
91 }
92 
ValueToFilePath(const Value & value)93 std::optional<FilePath> ValueToFilePath(const Value& value) {
94   if (!value.is_string())
95     return std::nullopt;
96   return FilePath::FromUTF8Unsafe(value.GetString());
97 }
98 
UnguessableTokenToValue(UnguessableToken token)99 Value UnguessableTokenToValue(UnguessableToken token) {
100   UnguessableTokenRepresentation repr;
101   repr.field.high = token.GetHighForSerialization();
102   repr.field.low = token.GetLowForSerialization();
103   return Value(HexEncode(repr.buffer, sizeof(repr.buffer)));
104 }
105 
ValueToUnguessableToken(const Value * value)106 std::optional<UnguessableToken> ValueToUnguessableToken(const Value* value) {
107   return value ? ValueToUnguessableToken(*value) : std::nullopt;
108 }
109 
ValueToUnguessableToken(const Value & value)110 std::optional<UnguessableToken> ValueToUnguessableToken(const Value& value) {
111   if (!value.is_string())
112     return std::nullopt;
113   UnguessableTokenRepresentation repr;
114   if (!HexStringToSpan(value.GetString(), repr.buffer))
115     return std::nullopt;
116   std::optional<base::UnguessableToken> token =
117       UnguessableToken::Deserialize(repr.field.high, repr.field.low);
118   if (!token.has_value()) {
119     return std::nullopt;
120   }
121   return token;
122 }
123 
124 }  // namespace base
125