ln.bson/ln.bson/BsonReader.cs

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);
}
}
}
}