ln.bson/ln.bson/BsonDocument.cs

184 lines
6.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Text;
using System.Text.Json;
namespace ln.bson
{
public class BsonDocument : BsonValue, IEnumerable<KeyValuePair<string, BsonValue>>
{
private Dictionary<string, BsonValue> _values = new Dictionary<string, BsonValue>();
public long StorageTag { get; set; }
public object UserTag { get; set; }
public BsonDocument():base(BsonType.Document){}
public override object ToNative()
{
Dictionary<string, object> native = new Dictionary<string, object>();
foreach (var bsonValue in _values)
native.Add(bsonValue.Key, bsonValue.Value.ToNative());
return native;
}
public override byte[] GetBytes()
{
byte[][] names = new byte[_values.Count][];
byte[][] bvalues = new byte[_values.Count][];
BsonType[] bsonTypes = new BsonType[_values.Count];
int n = 0;
int totalBytes = 0;
foreach (var bsonValue in _values)
{
bsonTypes[n] = bsonValue.Value.BsonType;
names[n] = Encoding.UTF8.GetBytes(bsonValue.Key);
bvalues[n] = bsonValue.Value.GetBytes();
totalBytes += names[n].Length + bvalues[n].Length;
n++;
}
byte[] containerBytes = new byte[totalBytes + 5 + (_values.Count << 1 )];
BitConverter.TryWriteBytes(containerBytes, containerBytes.Length);
int offset = 4;
for (n = 0; n < names.Length; n++)
{
containerBytes[offset] = (byte)bsonTypes[n];
Array.Copy(names[n], 0, containerBytes, offset + 1, names[n].Length);
Array.Copy(bvalues[n], 0, containerBytes, offset + 2 + names[n].Length, bvalues[n].Length);
offset += 2 + names[n].Length + bvalues[n].Length;
}
return containerBytes;
}
public BsonValue this[string name]
{
get => _values[name];
set => _values[name] = value;
}
public void Add(string name, BsonValue bsonValue) => _values.Add(name, bsonValue);
public void Remove(string name) => _values.Remove(name);
public bool Contains(string name) => _values.ContainsKey(name);
public IEnumerable<string> Keys => _values.Keys;
public IEnumerable<BsonValue> Values => _values.Values;
public IEnumerator<KeyValuePair<string, BsonValue>> GetEnumerator()
{
return _values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_values).GetEnumerator();
}
public override bool Equals(object? obj)
{
if (obj is BsonDocument other)
{
if (_values.Count == other._values.Count)
{
foreach (String key in _values.Keys)
{
if (!other._values.ContainsKey(key) || !_values[key].Equals(other._values[key]))
return false;
}
return true;
}
}
return false;
}
public override bool TryGetMember(GetMemberBinder binder, out object? result)
{
if (_values.TryGetValue(binder.Name, out BsonValue bsonValue))
{
result = bsonValue;
return true;
}
return base.TryGetMember(binder, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object? value)
{
Add(binder.Name, (BsonValue)value);
return true;
}
}
public class BsonArray : BsonValue, IEnumerable<BsonValue>
{
private List<BsonValue> _values = new List<BsonValue>();
public BsonArray():base(BsonType.Array){}
public override object ToNative()
{
object[] native = new object[_values.Count];
for (int n = 0; n < native.Length; n++)
native[n] = _values[n].ToNative();
return native;
}
public override byte[] GetBytes()
{
byte[][] names = new byte[_values.Count][];
byte[][] bvalues = new byte[_values.Count][];
BsonType[] bsonTypes = new BsonType[_values.Count];
int n = 0;
int totalBytes = 0;
foreach (var bsonValue in _values)
{
bsonTypes[n] = bsonValue.BsonType;
names[n] = Encoding.UTF8.GetBytes(n.ToString());
bvalues[n] = bsonValue.GetBytes();
totalBytes += names[n].Length + bvalues[n].Length;
n++;
}
byte[] containerBytes = new byte[totalBytes + 5 + (_values.Count << 1)];
BitConverter.TryWriteBytes(containerBytes, totalBytes);
int offset = 4;
for (n = 0; n < names.Length; n++)
{
containerBytes[offset] = (byte)bsonTypes[n];
Array.Copy(names[n], 0, containerBytes, offset + 1, names[n].Length);
Array.Copy(bvalues[n], 0, containerBytes, offset + 2 + names[n].Length, bvalues[n].Length);
offset += 2 + names[n].Length + bvalues[n].Length;
}
return containerBytes;
}
public BsonValue this[int i]
{
get => _values[i];
set => _values[i] = value;
}
public void Add(BsonValue bsonValue) => _values.Add(bsonValue);
public void Remove(BsonValue bsonValue) => _values.Remove(bsonValue);
public void RemoveAt(int i) => _values.RemoveAt(i);
public bool Contains(BsonValue bsonValue) => _values.Contains(bsonValue);
public int Length => _values.Count;
public IEnumerator<BsonValue> GetEnumerator()
{
return _values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_values).GetEnumerator();
}
}
}