-
Notifications
You must be signed in to change notification settings - Fork 1
/
APrimaryKey.cs
133 lines (114 loc) · 5.32 KB
/
APrimaryKey.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
using LINQPad;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using LPU = LINQPad.Util;
namespace Aerospike.Database.LINQPadDriver.Extensions
{
/// <summary>
/// A wrapper around Primary Key's <see cref="Object"/> value.
/// This is used as an aid so that casting is not required to perform comparison operations, etc.
/// This object also performs implicit casting to standard .Net data types while using LINQ...
/// </summary>
/// <seealso cref="AValue"/>
/// <seealso cref="AValue.ToValue(object)"/>
/// <seealso cref="AValue.ToValue(Client.Bin)"/>
/// <seealso cref="AValue.ToValue(Client.Value)"/>
/// <seealso cref="APrimaryKey.ToValue(Client.Key)"/>
/// <seealso cref="AValueHelper.ToAValue(Client.Bin)"/>
/// <seealso cref="AValueHelper.ToAPrimaryKey(Client.Key)"/>
/// <seealso cref="AValueHelper.ToAValue(Client.Value, string, string)"/>
/// <seealso cref="AValueHelper.ToAValue(object, string, string)"/>
/// <seealso cref="AValueHelper.ToAValue{T}(T?, string, string)"/>
/// <seealso cref="AValueHelper.Cast{TResult}(IEnumerable{AValue})"/>
/// <seealso cref="AValueHelper.OfType{TResult}(IEnumerable{AValue})"/>
public class APrimaryKey : AValue
{
public APrimaryKey(Aerospike.Client.Key key)
: base(key.userKey?.Object ?? key.digest, "PrimaryKey", "Value")
{
this.AerospikeKey = key;
}
public APrimaryKey(APrimaryKey clone)
: base(clone)
{
this.AerospikeKey = clone.AerospikeKey;
}
public Aerospike.Client.Key AerospikeKey { get; }
public override bool Equals(byte[] byteArray)
=> byteArray is not null && byteArray.Length == 20
&& this.AerospikeKey.digest.SequenceEqual(byteArray);
public override bool Equals(string digestStr)
=> (digestStr is not null
&& digestStr.Length == 42
&& digestStr[0] == '0'
&& char.ToLower(digestStr[1]) == 'x'
&& Helpers.HasHexValues(digestStr[2..])
&& this.Equals(Helpers.StringToByteArray(digestStr[2..])))
|| base.Equals(digestStr);
public override bool Equals(AValue value)
{
if(value is not null)
{
if(value is APrimaryKey pkValue)
return this.CompareDigest(pkValue.AerospikeKey);
if(value.Value is byte[] byteValue)
return this.Equals(byteValue);
}
return base.Equals(value);
}
public override bool Equals(Aerospike.Client.Value value)
{
if(value is not null && value.Object is byte[] bArray)
return this.Equals(bArray);
return base.Equals(value);
}
/// <summary>
/// If true, the PK has an actual value. If false, the digest is only provided.
/// </summary>
public bool HasKeyValue { get => this.AerospikeKey.userKey?.Object is not null; }
public static APrimaryKey ToValue(Aerospike.Client.Key key) => new APrimaryKey(key);
public override int GetHashCode() => this.DigestRequired()
? this.AerospikeKey.digest.GetHashCode()
: base.GetHashCode();
override public object ToDump()
{
return this.DigestRequired()
? LPU.WithStyle($"Digest<0x{Helpers.ByteArrayToString(this.AerospikeKey.digest)}>",
"color:DarkSlateGray")
: this.Value;
}
public override string ToString() => this.DigestRequired()
? Helpers.ByteArrayToString(this.AerospikeKey.digest)
: base.ToString();
protected override bool DigestRequired() => this.AerospikeKey.userKey?.Object is null;
protected override bool CompareDigest(object value)
{
if (value is null) return false;
if(ReferenceEquals(this, value)) return true;
if(value is Aerospike.Client.Key key)
{
if(key.userKey is null) return this.AerospikeKey.digest.SequenceEqual(key.digest);
return this.CompareDigest(key.userKey);
}
else if (value is Aerospike.Client.Value avalue)
{
return this.AerospikeKey.digest.SequenceEqual(Aerospike.Client.Key.ComputeDigest(this.AerospikeKey.setName,
avalue));
}
else if(value is APrimaryKey pkValue)
{
return this.CompareDigest(pkValue.AerospikeKey);
}
else if(value is AValue aValue)
{
return this.CompareDigest(aValue.Value);
}
var dbValue = Helpers.ConvertToAerospikeType(value);
return this.AerospikeKey.digest.SequenceEqual(Aerospike.Client.Key.ComputeDigest(this.AerospikeKey.setName,
Aerospike.Client.Value.Get(dbValue)));
}
}
}