/
CborWriter.Integer.cs
145 lines (135 loc) · 6.7 KB
/
CborWriter.Integer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Buffers.Binary;
namespace System.Formats.Cbor
{
public partial class CborWriter
{
// Implements major type 0,1 encoding per https://tools.ietf.org/html/rfc7049#section-2.1
/// <summary>Writes a value as a signed integer encoding (major types 0,1)</summary>
/// <param name="value">The value to write</param>
/// <exception cref="InvalidOperationException"><para>Writing a new value exceeds the definite length of the parent data item.</para>
/// <para>-or-</para>
/// <para>The major type of the encoded value is not permitted in the parent data item.</para>
/// <para>-or-</para>
/// <para>The written data is not accepted under the current conformance mode.</para></exception>
public void WriteInt32(int value) => WriteInt64(value);
/// <summary>Writes the provided value as a signed integer encoding (major types 0,1)</summary>
/// <param name="value">The value to write</param>
/// <exception cref="InvalidOperationException"><para>Writing a new value exceeds the definite length of the parent data item.</para>
/// <para>-or-</para>
/// <para>The major type of the encoded value is not permitted in the parent data item.</para>
/// <para>-or-</para>
/// <para>The written data is not accepted under the current conformance mode.</para></exception>
public void WriteInt64(long value)
{
if (value < 0)
{
ulong unsignedRepresentation = (value == long.MinValue) ? (ulong)long.MaxValue : (ulong)(-value) - 1;
WriteUnsignedInteger(CborMajorType.NegativeInteger, unsignedRepresentation);
}
else
{
WriteUnsignedInteger(CborMajorType.UnsignedInteger, (ulong)value);
}
AdvanceDataItemCounters();
}
/// <summary>Writes a value as an unsigned integer encoding (major type 0).</summary>
/// <param name="value">The value to write</param>
/// <exception cref="InvalidOperationException"><para>Writing a new value exceeds the definite length of the parent data item.</para>
/// <para>-or-</para>
/// <para>The major type of the encoded value is not permitted in the parent data item.</para>
/// <para>-or-</para>
/// <para>The written data is not accepted under the current conformance mode.</para></exception>
[CLSCompliant(false)]
public void WriteUInt32(uint value) => WriteUInt64(value);
/// <summary>Writes a value as an unsigned integer encoding (major type 0).</summary>
/// <param name="value">The value to write</param>
/// <exception cref="InvalidOperationException"><para>Writing a new value exceeds the definite length of the parent data item.</para>
/// <para>-or-</para>
/// <para>The major type of the encoded value is not permitted in the parent data item.</para>
/// <para>-or-</para>
/// <para>The written data is not accepted under the current conformance mode.</para></exception>
[CLSCompliant(false)]
public void WriteUInt64(ulong value)
{
WriteUnsignedInteger(CborMajorType.UnsignedInteger, value);
AdvanceDataItemCounters();
}
/// <summary>Writes the provided value as a CBOR negative integer representation (major type 1).</summary>
/// <param name="value">An unsigned integer denoting -1 minus the integer.</param>
/// <exception cref="InvalidOperationException"><para>Writing a new value exceeds the definite length of the parent data item.</para>
/// <para>-or-</para>
/// <para>The major type of the encoded value is not permitted in the parent data item.</para>
/// <para>-or-</para>
/// <para>The written data is not accepted under the current conformance mode.</para></exception>
/// <remarks>
/// This method supports encoding integers between -18446744073709551616 and -1.
/// Useful for handling values that do not fit in the <see cref="long" /> type.
/// </remarks>
[CLSCompliant(false)]
public void WriteCborNegativeIntegerRepresentation(ulong value)
{
WriteUnsignedInteger(CborMajorType.NegativeInteger, value);
AdvanceDataItemCounters();
}
private void WriteUnsignedInteger(CborMajorType type, ulong value)
{
if (value < (byte)CborAdditionalInfo.Additional8BitData)
{
EnsureWriteCapacity(1);
WriteInitialByte(new CborInitialByte(type, (CborAdditionalInfo)value));
}
else if (value <= byte.MaxValue)
{
EnsureWriteCapacity(1 + sizeof(byte));
WriteInitialByte(new CborInitialByte(type, CborAdditionalInfo.Additional8BitData));
_buffer[_offset++] = (byte)value;
}
else if (value <= ushort.MaxValue)
{
EnsureWriteCapacity(1 + sizeof(ushort));
WriteInitialByte(new CborInitialByte(type, CborAdditionalInfo.Additional16BitData));
BinaryPrimitives.WriteUInt16BigEndian(_buffer.AsSpan(_offset), (ushort)value);
_offset += sizeof(ushort);
}
else if (value <= uint.MaxValue)
{
EnsureWriteCapacity(1 + sizeof(uint));
WriteInitialByte(new CborInitialByte(type, CborAdditionalInfo.Additional32BitData));
BinaryPrimitives.WriteUInt32BigEndian(_buffer.AsSpan(_offset), (uint)value);
_offset += sizeof(uint);
}
else
{
EnsureWriteCapacity(1 + sizeof(ulong));
WriteInitialByte(new CborInitialByte(type, CborAdditionalInfo.Additional64BitData));
BinaryPrimitives.WriteUInt64BigEndian(_buffer.AsSpan(_offset), value);
_offset += sizeof(ulong);
}
}
private static int GetIntegerEncodingLength(ulong value)
{
if (value < (byte)CborAdditionalInfo.Additional8BitData)
{
return 1;
}
else if (value <= byte.MaxValue)
{
return 1 + sizeof(byte);
}
else if (value <= ushort.MaxValue)
{
return 1 + sizeof(ushort);
}
else if (value <= uint.MaxValue)
{
return 1 + sizeof(uint);
}
else
{
return 1 + sizeof(ulong);
}
}
}
}