forked from npgsql/npgsql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJsonbHandler.cs
More file actions
executable file
·108 lines (92 loc) · 3.23 KB
/
JsonbHandler.cs
File metadata and controls
executable file
·108 lines (92 loc) · 3.23 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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Npgsql.BackendMessages;
using NpgsqlTypes;
namespace Npgsql.TypeHandlers
{
/// <summary>
/// JSONB binary encoding is a simple UTF8 string, but prepended with a version number.
/// </summary>
[TypeMapping("jsonb", NpgsqlDbType.Jsonb)]
class JsonbHandler : TypeHandler<string>, IChunkingTypeWriter, IChunkingTypeReader<string>
{
/// <summary>
/// Prepended to the string in the wire encoding
/// </summary>
const byte ProtocolVersion = 1;
/// <summary>
/// Indicates whether the prepended version byte has already been read or written
/// </summary>
bool _handledVersion;
NpgsqlBuffer _buf;
/// <summary>
/// The text handler which does most of the encoding/decoding work.
/// </summary>
readonly TextHandler _textHandler;
public JsonbHandler()
{
_textHandler = new TextHandler();
}
#region Write
public int ValidateAndGetLength(object value, ref LengthCache lengthCache, NpgsqlParameter parameter=null)
{
if (lengthCache == null) {
lengthCache = new LengthCache(1);
}
if (lengthCache.IsPopulated) {
return lengthCache.Get();
}
// Add one byte for the prepended version number
return lengthCache.Set(_textHandler.DoValidateAndGetLength(value, parameter)+1);
}
public void PrepareWrite(object value, NpgsqlBuffer buf, LengthCache lengthCache, NpgsqlParameter parameter)
{
_textHandler.PrepareWrite(value, buf, lengthCache, parameter);
_buf = buf;
_handledVersion = false;
}
public bool Write(ref DirectBuffer directBuf)
{
if (!_handledVersion)
{
if (_buf.WriteSpaceLeft < 1) { return false; }
_buf.WriteByte(ProtocolVersion);
_handledVersion = true;
}
if (!_textHandler.Write(ref directBuf)) { return false; }
_buf = null;
return true;
}
#endregion
#region Read
public void PrepareRead(NpgsqlBuffer buf, int len, FieldDescription fieldDescription)
{
// Subtract one byte for the version number
_textHandler.PrepareRead(buf, fieldDescription, len-1);
_buf = buf;
_handledVersion = false;
}
public bool Read(out string result)
{
if (!_handledVersion)
{
if (_buf.ReadBytesLeft < 1)
{
result = null;
return false;
}
var version = _buf.ReadByte();
if (version != 1) {
throw new NotSupportedException(String.Format("Don't know how to decode JSONB with wire format {0}, your connection is now broken", version));
}
_handledVersion = true;
}
if (!_textHandler.Read(out result)) { return false; }
_buf = null;
return true;
}
#endregion
}
}