184 lines
6.2 KiB
C#
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();
|
|
}
|
|
}
|
|
} |