103 lines
4.2 KiB
C#
103 lines
4.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using ln.type;
|
|
|
|
namespace ln.bson
|
|
{
|
|
public static class BsonReader
|
|
{
|
|
public static BsonDocument ReadDocument(byte[] buffer) => ReadDocument(buffer, 0, buffer.Length);
|
|
public static BsonDocument ReadDocument(byte[] buffer, int offset) => ReadDocument(buffer, offset, buffer.Length - offset);
|
|
|
|
public static BsonDocument ReadDocument(byte[] buffer, int offset, int length)
|
|
{
|
|
using (var ms = new MemoryStream(buffer, offset, length))
|
|
return ReadDocument(ms);
|
|
}
|
|
|
|
public static BsonDocument ReadDocument(Stream stream)
|
|
{
|
|
BsonDocument bsonDocument = new BsonDocument();
|
|
ReadDocumentItems(stream, ((s, value) => bsonDocument.Add(s,value)));
|
|
return bsonDocument;
|
|
}
|
|
private static BsonArray ReadArray(Stream stream)
|
|
{
|
|
BsonArray bsonArray = new BsonArray();
|
|
ReadDocumentItems(stream, ((s, value) => bsonArray.Add(value)));
|
|
return bsonArray;
|
|
}
|
|
|
|
private static void ReadDocumentItems(Stream stream, Action<string, BsonValue> appender)
|
|
{
|
|
int documentLength = stream.ReadInteger();
|
|
BsonType bsonType = BsonType.Null;
|
|
while (bsonType != BsonType.EndOfDocument)
|
|
{
|
|
bsonType = (BsonType)stream.ReadByte();
|
|
if (bsonType == BsonType.EndOfDocument)
|
|
return;
|
|
|
|
string name = stream.ReadCString();
|
|
BsonValue bsonValue = null;
|
|
switch (bsonType)
|
|
{
|
|
case BsonType.Boolean:
|
|
if (stream.ReadByte() == 0)
|
|
bsonValue = BsonBoolean.False;
|
|
else
|
|
bsonValue = BsonBoolean.True;
|
|
break;
|
|
case BsonType.Double:
|
|
bsonValue = new BsonDouble(stream.ReadDouble());
|
|
break;
|
|
case BsonType.Int32:
|
|
bsonValue = new BsonInt32(stream.ReadInteger());
|
|
break;
|
|
case BsonType.Int64:
|
|
bsonValue = new BsonInt64(stream.ReadLong());
|
|
break;
|
|
case BsonType.Null:
|
|
bsonValue = BsonNull.Instance;
|
|
break;
|
|
case BsonType.Binary:
|
|
int blength = stream.ReadInteger();
|
|
BsonBinarySubType subType = (BsonBinarySubType)stream.ReadByte();
|
|
switch (subType)
|
|
{
|
|
case BsonBinarySubType.UuidOld:
|
|
case BsonBinarySubType.Uuid:
|
|
if (blength != 16)
|
|
throw new ArgumentOutOfRangeException(nameof(blength));
|
|
bsonValue = new BsonGuid(stream.ReadBytes(blength));
|
|
break;
|
|
default:
|
|
bsonValue = new BsonBinary(subType, stream.ReadBytes(blength));
|
|
break;
|
|
}
|
|
break;
|
|
case BsonType.String:
|
|
blength = stream.ReadInteger();
|
|
bsonValue = new BsonString(Encoding.UTF8.GetString(stream.ReadBytes(blength),0, blength-1));
|
|
break;
|
|
case BsonType.DateTime:
|
|
bsonValue = new BsonDateTime(DateTimeExtensions.FromUnixTimeMilliseconds(stream.ReadLong()));
|
|
break;
|
|
case BsonType.Document:
|
|
bsonValue = ReadDocument(stream);
|
|
break;
|
|
case BsonType.Array:
|
|
bsonValue = ReadArray(stream);
|
|
break;
|
|
case BsonType.EndOfDocument:
|
|
return;
|
|
default:
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
appender(name, bsonValue);
|
|
}
|
|
}
|
|
}
|
|
} |