131 lines
3.8 KiB
C#
Executable File
131 lines
3.8 KiB
C#
Executable File
namespace ZB.MOM.WW.CBDD.Bson.Schema;
|
|
|
|
public class BsonField
|
|
{
|
|
/// <summary>
|
|
/// Gets the field name.
|
|
/// </summary>
|
|
public required string Name { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets the field BSON type.
|
|
/// </summary>
|
|
public BsonType Type { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets a value indicating whether the field is nullable.
|
|
/// </summary>
|
|
public bool IsNullable { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets the nested schema when this field is a document.
|
|
/// </summary>
|
|
public BsonSchema? NestedSchema { get; init; }
|
|
|
|
/// <summary>
|
|
/// Gets the array item type when this field is an array.
|
|
/// </summary>
|
|
public BsonType? ArrayItemType { get; init; }
|
|
|
|
/// <summary>
|
|
/// Writes this field definition to BSON.
|
|
/// </summary>
|
|
/// <param name="writer">The BSON writer.</param>
|
|
public void ToBson(ref BsonSpanWriter writer)
|
|
{
|
|
int size = writer.BeginDocument();
|
|
writer.WriteString("n", Name);
|
|
writer.WriteInt32("t", (int)Type);
|
|
writer.WriteBoolean("b", IsNullable);
|
|
|
|
if (NestedSchema != null)
|
|
{
|
|
writer.WriteElementHeader(BsonType.Document, "s");
|
|
NestedSchema.ToBson(ref writer);
|
|
}
|
|
|
|
if (ArrayItemType != null) writer.WriteInt32("a", (int)ArrayItemType.Value);
|
|
|
|
writer.EndDocument(size);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads a field definition from BSON.
|
|
/// </summary>
|
|
/// <param name="reader">The BSON reader.</param>
|
|
/// <returns>The deserialized field.</returns>
|
|
public static BsonField FromBson(ref BsonSpanReader reader)
|
|
{
|
|
reader.ReadInt32(); // Read doc size
|
|
|
|
var name = "";
|
|
var type = BsonType.Null;
|
|
var isNullable = false;
|
|
BsonSchema? nestedSchema = null;
|
|
BsonType? arrayItemType = null;
|
|
|
|
while (reader.Remaining > 1)
|
|
{
|
|
var btype = reader.ReadBsonType();
|
|
if (btype == BsonType.EndOfDocument) break;
|
|
|
|
string key = reader.ReadElementHeader();
|
|
switch (key)
|
|
{
|
|
case "n": name = reader.ReadString(); break;
|
|
case "t": type = (BsonType)reader.ReadInt32(); break;
|
|
case "b": isNullable = reader.ReadBoolean(); break;
|
|
case "s": nestedSchema = BsonSchema.FromBson(ref reader); break;
|
|
case "a": arrayItemType = (BsonType)reader.ReadInt32(); break;
|
|
default: reader.SkipValue(btype); break;
|
|
}
|
|
}
|
|
|
|
return new BsonField
|
|
{
|
|
Name = name,
|
|
Type = type,
|
|
IsNullable = isNullable,
|
|
NestedSchema = nestedSchema,
|
|
ArrayItemType = arrayItemType
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Computes a hash representing the field definition.
|
|
/// </summary>
|
|
/// <returns>The computed hash value.</returns>
|
|
public long GetHash()
|
|
{
|
|
var hash = new HashCode();
|
|
hash.Add(Name);
|
|
hash.Add((int)Type);
|
|
hash.Add(IsNullable);
|
|
hash.Add(ArrayItemType);
|
|
if (NestedSchema != null) hash.Add(NestedSchema.GetHash());
|
|
return hash.ToHashCode();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether this field is equal to another field.
|
|
/// </summary>
|
|
/// <param name="other">The other field.</param>
|
|
/// <returns><see langword="true" /> if the fields are equal; otherwise, <see langword="false" />.</returns>
|
|
public bool Equals(BsonField? other)
|
|
{
|
|
if (other == null) return false;
|
|
return GetHash() == other.GetHash();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override bool Equals(object? obj)
|
|
{
|
|
return Equals(obj as BsonField);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override int GetHashCode()
|
|
{
|
|
return (int)GetHash();
|
|
}
|
|
} |