private static string valueToText(this BsonValue value, BsonToStringFormat format, string leftPad = null)
        {
            switch (value.Type)
            {
            case BsonType.Null:
                return("null");

            case BsonType.Int32:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? value.AsInt32.ToString() : $"Int({value.AsInt32})");

            case BsonType.Int64:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? value.AsInt64.ToString() : $"Long({value.AsInt64})");

            case BsonType.Double:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? value.AsDouble.ToString("0.0################", NumberFormatInfo.InvariantInfo) : $"Double({value.AsDouble.ToString("0.0################", NumberFormatInfo.InvariantInfo)})");

            case BsonType.Decimal:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? value.AsDecimal.ToString("0.0################", NumberFormatInfo.InvariantInfo) : $"Decimal({value.AsDecimal.ToString("0.0################", NumberFormatInfo.InvariantInfo)})");

            case BsonType.String:
                return($"\"{value.AsString.EscapeStringAsJson()}\"");

            case BsonType.Document:
                return(value.AsDocument.ToText(format, leftPad));

            case BsonType.Array:
                return(value.AsArray.valueToText(format, leftPad));

            case BsonType.Binary:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? $"{{\"$binary\" : \"{Convert.ToBase64String(value.AsBinary).EscapeStringAsJson()}\"}}" : $"Binary(\"{Convert.ToBase64String(value.AsBinary).EscapeStringAsJson()}\")");

            case BsonType.ObjectId:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? $"{{\"$oid\" : \"{value.AsObjectId}\"}}" : $"ObjectId(\"{value.AsObjectId}\")");

            case BsonType.Guid:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? $"{{\"$guid\" : \"{value.AsGuid}\"}}" : $"Guid(\"{value.AsGuid}\")");

            case BsonType.Boolean:
                return(value.AsBoolean ? "true" : "false");

            case BsonType.DateTime:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? $"\"{value.AsDateTime:yyyy-MM-ddTHH:mm:ss.fffZ}\"" : $"ISODate(\"{value.AsDateTime:O}\")");

            case BsonType.MaxValue:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? "{\"$maxValue\" : \"\"}" : "MaxValue()");

            case BsonType.MinValue:
                return(format.HasFlag(BsonToStringFormat.JsonFriendly) ? "{\"$minValue\" : \"\"}" : "MinValue()");
            }

            throw new NotSupportedException();
        }
        /// <summary>
        /// Converts the BSON document to an indented formatted string.
        /// </summary>
        public static string ToText(this BsonDocument doc, BsonToStringFormat format = BsonToStringFormat.BsonFriendly | BsonToStringFormat.Indent, string leftPad = null)
        {
            if (doc.Count == 0)
            {
                return("{}");
            }

            var builder         = new StringBuilder();
            var isFirstProperty = true;

            if (format.HasFlag(BsonToStringFormat.Indent))
            {
                builder.AppendLine("{");
            }
            else
            {
                builder.Append("{");
            }

            foreach (var property in doc)
            {
                if (isFirstProperty)
                {
                    isFirstProperty = false;
                }
                else if (format.HasFlag(BsonToStringFormat.Indent))
                {
                    builder.AppendLine(",");
                }
                else
                {
                    builder.Append(", ");
                }

                var key = $"\"{property.Key.EscapeStringAsJson()}\"";

                builder.Append(format.HasFlag(BsonToStringFormat.Indent) ?
                               $"{leftPad}\t{key} : {property.Value.valueToText(format, $"{leftPad}\t")}" :
                               $"{key} : {property.Value.valueToText(format)}");
            }

            if (format.HasFlag(BsonToStringFormat.Indent) && !isFirstProperty)
            {
                builder.AppendLine();
            }

            builder.Append(format.HasFlag(BsonToStringFormat.Indent) ? $"{leftPad}}}" : "}");

            return(builder.ToString());
        }
        //bson to string
        private static string valueToText(this BsonArray value, BsonToStringFormat format, string leftPad = null)
        {
            if (value.Count == 0)
            {
                return("[]");
            }

            var builder        = new StringBuilder();
            var isFirstElement = true;

            if (format.HasFlag(BsonToStringFormat.Indent))
            {
                builder.AppendLine("[");
            }
            else
            {
                builder.Append("[");
            }

            foreach (var item in value)
            {
                if (isFirstElement)
                {
                    isFirstElement = false;
                }
                else if (format.HasFlag(BsonToStringFormat.Indent))
                {
                    builder.AppendLine(",");
                }
                else
                {
                    builder.Append(", ");
                }

                builder.Append(format.HasFlag(BsonToStringFormat.Indent) ?
                               $"{leftPad}\t{item.valueToText(format, $"{leftPad}\t")}" :
                               item.valueToText(format));
            }

            if (format.HasFlag(BsonToStringFormat.Indent) && !isFirstElement)
            {
                builder.AppendLine();
            }

            builder.Append(format.HasFlag(BsonToStringFormat.Indent) ? $"{leftPad}]" : "]");

            return(builder.ToString());
        }