xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_data_writer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 "quiche/quic/core/quic_data_writer.h"
6 
7 #include <algorithm>
8 #include <limits>
9 
10 #include "absl/strings/string_view.h"
11 #include "quiche/quic/core/crypto/quic_random.h"
12 #include "quiche/quic/core/quic_constants.h"
13 #include "quiche/quic/platform/api/quic_bug_tracker.h"
14 #include "quiche/quic/platform/api/quic_flags.h"
15 #include "quiche/common/quiche_endian.h"
16 
17 namespace quic {
18 
QuicDataWriter(size_t size,char * buffer)19 QuicDataWriter::QuicDataWriter(size_t size, char* buffer)
20     : quiche::QuicheDataWriter(size, buffer) {}
21 
QuicDataWriter(size_t size,char * buffer,quiche::Endianness endianness)22 QuicDataWriter::QuicDataWriter(size_t size, char* buffer,
23                                quiche::Endianness endianness)
24     : quiche::QuicheDataWriter(size, buffer, endianness) {}
25 
~QuicDataWriter()26 QuicDataWriter::~QuicDataWriter() {}
27 
WriteUFloat16(uint64_t value)28 bool QuicDataWriter::WriteUFloat16(uint64_t value) {
29   uint16_t result;
30   if (value < (UINT64_C(1) << kUFloat16MantissaEffectiveBits)) {
31     // Fast path: either the value is denormalized, or has exponent zero.
32     // Both cases are represented by the value itself.
33     result = static_cast<uint16_t>(value);
34   } else if (value >= kUFloat16MaxValue) {
35     // Value is out of range; clamp it to the maximum representable.
36     result = std::numeric_limits<uint16_t>::max();
37   } else {
38     // The highest bit is between position 13 and 42 (zero-based), which
39     // corresponds to exponent 1-30. In the output, mantissa is from 0 to 10,
40     // hidden bit is 11 and exponent is 11 to 15. Shift the highest bit to 11
41     // and count the shifts.
42     uint16_t exponent = 0;
43     for (uint16_t offset = 16; offset > 0; offset /= 2) {
44       // Right-shift the value until the highest bit is in position 11.
45       // For offset of 16, 8, 4, 2 and 1 (binary search over 1-30),
46       // shift if the bit is at or above 11 + offset.
47       if (value >= (UINT64_C(1) << (kUFloat16MantissaBits + offset))) {
48         exponent += offset;
49         value >>= offset;
50       }
51     }
52 
53     QUICHE_DCHECK_GE(exponent, 1);
54     QUICHE_DCHECK_LE(exponent, kUFloat16MaxExponent);
55     QUICHE_DCHECK_GE(value, UINT64_C(1) << kUFloat16MantissaBits);
56     QUICHE_DCHECK_LT(value, UINT64_C(1) << kUFloat16MantissaEffectiveBits);
57 
58     // Hidden bit (position 11) is set. We should remove it and increment the
59     // exponent. Equivalently, we just add it to the exponent.
60     // This hides the bit.
61     result = static_cast<uint16_t>(value + (exponent << kUFloat16MantissaBits));
62   }
63 
64   if (endianness() == quiche::NETWORK_BYTE_ORDER) {
65     result = quiche::QuicheEndian::HostToNet16(result);
66   }
67   return WriteBytes(&result, sizeof(result));
68 }
69 
WriteConnectionId(QuicConnectionId connection_id)70 bool QuicDataWriter::WriteConnectionId(QuicConnectionId connection_id) {
71   if (connection_id.IsEmpty()) {
72     return true;
73   }
74   return WriteBytes(connection_id.data(), connection_id.length());
75 }
76 
WriteLengthPrefixedConnectionId(QuicConnectionId connection_id)77 bool QuicDataWriter::WriteLengthPrefixedConnectionId(
78     QuicConnectionId connection_id) {
79   return WriteUInt8(connection_id.length()) && WriteConnectionId(connection_id);
80 }
81 
WriteRandomBytes(QuicRandom * random,size_t length)82 bool QuicDataWriter::WriteRandomBytes(QuicRandom* random, size_t length) {
83   char* dest = BeginWrite(length);
84   if (!dest) {
85     return false;
86   }
87 
88   random->RandBytes(dest, length);
89   IncreaseLength(length);
90   return true;
91 }
92 
WriteInsecureRandomBytes(QuicRandom * random,size_t length)93 bool QuicDataWriter::WriteInsecureRandomBytes(QuicRandom* random,
94                                               size_t length) {
95   char* dest = BeginWrite(length);
96   if (!dest) {
97     return false;
98   }
99 
100   random->InsecureRandBytes(dest, length);
101   IncreaseLength(length);
102   return true;
103 }
104 
105 }  // namespace quic
106