namespace ZB.MOM.WW.CBDD.Bson.Schema;
public class BsonField
{
///
/// Gets the field name.
///
public required string Name { get; init; }
///
/// Gets the field BSON type.
///
public BsonType Type { get; init; }
///
/// Gets a value indicating whether the field is nullable.
///
public bool IsNullable { get; init; }
///
/// Gets the nested schema when this field is a document.
///
public BsonSchema? NestedSchema { get; init; }
///
/// Gets the array item type when this field is an array.
///
public BsonType? ArrayItemType { get; init; }
///
/// Writes this field definition to BSON.
///
/// The BSON writer.
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);
}
///
/// Reads a field definition from BSON.
///
/// The BSON reader.
/// The deserialized field.
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
};
}
///
/// Computes a hash representing the field definition.
///
/// The computed hash value.
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();
}
///
/// Determines whether this field is equal to another field.
///
/// The other field.
/// if the fields are equal; otherwise, .
public bool Equals(BsonField? other)
{
if (other == null) return false;
return GetHash() == other.GetHash();
}
///
public override bool Equals(object? obj)
{
return Equals(obj as BsonField);
}
///
public override int GetHashCode()
{
return (int)GetHash();
}
}