forked from npgsql/npgsql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathByteaHandler.cs
More file actions
114 lines (101 loc) · 4.8 KB
/
ByteaHandler.cs
File metadata and controls
114 lines (101 loc) · 4.8 KB
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
#region License
// The PostgreSQL License
//
// Copyright (C) 2017 The Npgsql Development Team
//
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph and the following two paragraphs appear in all copies.
//
// IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
// DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#endregion
using System;
using System.Threading.Tasks;
using Npgsql.BackendMessages;
using NpgsqlTypes;
using System.Data;
using JetBrains.Annotations;
using Npgsql.TypeHandling;
using Npgsql.TypeMapping;
namespace Npgsql.TypeHandlers
{
/// <remarks>
/// http://www.postgresql.org/docs/current/static/datatype-binary.html
/// </remarks>
[TypeMapping("bytea", NpgsqlDbType.Bytea, DbType.Binary, new[] { typeof(byte[]), typeof(ArraySegment<byte>) })]
class ByteaHandler : NpgsqlTypeHandler<byte[]>, INpgsqlTypeHandler<ArraySegment<byte>>
{
public override async ValueTask<byte[]> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
{
var bytes = new byte[len];
var pos = 0;
while (true)
{
var toRead = Math.Min(len - pos, buf.ReadBytesLeft);
buf.ReadBytes(bytes, pos, toRead);
pos += toRead;
if (pos == len)
break;
await buf.ReadMore(async);
}
return bytes;
}
ValueTask<ArraySegment<byte>> INpgsqlTypeHandler<ArraySegment<byte>>.Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription)
{
buf.Skip(len);
throw new NpgsqlSafeReadException(new NotSupportedException("Only writing ArraySegment<byte> to PostgreSQL bytea is supported, no reading."));
}
#region Write
public override int ValidateAndGetLength(byte[] value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
=> parameter == null || parameter.Size <= 0 || parameter.Size >= value.Length
? value.Length
: parameter.Size;
public int ValidateAndGetLength(ArraySegment<byte> value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
=> parameter == null || parameter.Size <= 0 || parameter.Size >= value.Count
? value.Count
: parameter.Size;
public override async Task Write(byte[] value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, [CanBeNull] NpgsqlParameter parameter, bool async)
{
var len = parameter == null || parameter.Size <= 0 || parameter.Size >= value.Length
? value.Length
: parameter.Size;
// The entire array fits in our buffer, copy it into the buffer as usual.
if (len <= buf.WriteSpaceLeft)
{
buf.WriteBytes(value, 0, len);
return;
}
// The segment is larger than our buffer. Flush whatever is currently in the buffer and
// write the array directly to the socket.
await buf.Flush(async);
buf.DirectWrite(value, 0, len);
}
public async Task Write(ArraySegment<byte> value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, [CanBeNull] NpgsqlParameter parameter, bool async)
{
if (!(parameter == null || parameter.Size <= 0 || parameter.Size >= value.Count))
value = new ArraySegment<byte>(value.Array, value.Offset, Math.Min(parameter.Size, value.Count));
// The entire segment fits in our buffer, copy it as usual.
if (value.Count <= buf.WriteSpaceLeft)
{
buf.WriteBytes(value.Array, value.Offset, value.Count);
return;
}
// The segment is larger than our buffer. Flush whatever is currently in the buffer and
// write the array directly to the socket.
await buf.Flush(async);
buf.DirectWrite(value.Array, value.Offset, value.Count);
}
#endregion
}
}