<commit_before>﻿// Copyright (c) <NAME>. All rights reserved. See license.txt in the project root for license information.

namespace Aqua.Newtonsoft.Json.Converters
{
    using Aqua.TypeSystem;
    using global::Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public static class JsonConverterHelper
    {
        private static readonly Dictionary<Type, Func<JsonReader, object?>> _typeReaders = new (Type Type, Func<JsonReader, object?> Reader)[]
            {
                (typeof(bool), r => r.ReadAsBoolean()),
                (typeof(byte[]), r => r.ReadAsBytes()),
                (typeof(DateTime), r => r.ReadAsDateTime()),
                (typeof(DateTimeOffset), r => r.ReadAsDateTimeOffset()),
                (typeof(decimal), r => r.ReadAsDecimal()),
                (typeof(double), r => r.ReadAsDouble()),
                (typeof(int), r => r.ReadAsInt32()),
                (typeof(string), r => r.ReadAsString()),
            }
            .SelectMany(x => x.Type.IsClass
                ? new[] { x }
                : new[] { x, (Type: typeof(Nullable<>).MakeGenericType(x.Type), x.Reader) })
            .ToDictionary(x => x.Type, x => x.Reader);

        public static string IdToken => "$id";

        public static string RefToken => "$ref";

        public static bool IsCollection(this TypeInfo? type)
        {
            if (type is null)
            {
                return false;
            }

            if (type.IsArray && type.ToType() != typeof(byte[]))
            {
                return true;
            }

            if (type.IsGenericType && type.ToType().GetGenericTypeDefinition() == typeof(List<>))
            {
                return true;
            }

            return false;
        }

        public static JsonSerializationException CreateException(this JsonReader reader, string message)
            => reader.CheckNotNull(nameof(reader)) is IJsonLineInfo lineInfo && lineInfo.HasLineInfo()
            ? new JsonSerializationException(message, reader.Path, lineInfo.LineNumber, lineInfo.LinePosition, null)
            : new JsonSerializationException(message);

        public static void Advance(this JsonReader reader, string? errorMessage = null)
        {
            reader.CheckNotNull(nameof(reader));
            if (!reader.CheckNotNull(nameof(reader)).Read())
            {
                throw reader.CreateException(errorMessage ?? "Unexpected token structure.");
            }
        }

        public static void AssertProperty(this JsonReader reader, string propertyName, bool advance = true)
        {
            reader.CheckNotNull(nameof(reader));
            if (advance)
            {
                reader.Advance();
            }

            if (!IsProperty(reader, propertyName))
            {
                throw reader.CreateException($"Expected token '{propertyName}'.");
            }
        }

        public static T? Read<T>(this JsonReader reader, JsonSerializer serializer)
            => reader.CheckNotNull(nameof(reader)).TryRead(serializer, out T? result)
            ? result
            : throw reader.CreateException("Unexpected token structure.");

        public static object? Read(this JsonReader reader, TypeInfo? type, JsonSerializer serializer)
            => reader.CheckNotNull(nameof(reader)).Read(type.MapTypeInfo(), serializer);

        public static object? Read(this JsonReader reader, Type? type, JsonSerializer serializer)
            => reader.CheckNotNull(nameof(reader)).TryRead(type, serializer, out object? result)
            ? result
            : throw reader.CreateException("Unexpected token structure.");

        public static bool TryRead<T>(this JsonReader reader, JsonSerializer serializer, out T? value)
        {
            var result = TryRead(reader, typeof(T), serializer, out var v);
            value = result && v is T x ? x : default;
            return result;
        }

        public static bool TryRead(this JsonReader reader, TypeInfo? type, JsonSerializer serializer, out object? result)
            => reader.TryRead(type.MapTypeInfo(), serializer, out result);

        public static bool TryRead(this JsonReader reader, Type? type, JsonSerializer serializer, out object? result)
        {
            reader.CheckNotNull(nameof(reader));
            serializer.CheckNotNull(nameof(serializer));

            if (type is not null && _typeReaders.TryGetValue(type, out var read))
            {
                result = read(reader);
                return reader.TokenType != JsonToken.EndArray
                    && reader.TokenType != JsonToken.EndObject;
            }

            reader.Advance($"Expected token object of type '{type}'.");

            switch (reader.TokenType)
            {
                case JsonToken.String:
                    if (type != typeof(TypeInfo))
                    {
                        var text = reader.Value as string;
                        result = type == typeof(char) && text?.Length > 0
                            ? text[0]
                            : text;
                        return true;
                    }

                    break;

                case JsonToken.Null:
                    result = default;
                    return true;

                case JsonToken.EndArray:
                case JsonToken.EndObject:
                    result = default;
                    return false;

                default:
                    break;
            }

            result = serializer.Deserialize(reader, type);
            return true;
        }

        public static void AssertStartObject(this JsonReader reader, bool advance = true)
        {
            reader.CheckNotNull(nameof(reader));
            if (advance && !reader.Read())
            {
                throw reader.CreateException($"Expected start object.");
            }

            if (reader.TokenType != JsonToken.StartObject)<commit_msg>remove empty default case<commit_after>﻿// Copyright (c) <NAME>. All rights reserved. See license.txt in the project root for license information.

namespace Aqua.Newtonsoft.Json.Converters
{
    using Aqua.TypeSystem;
    using global::Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public static class JsonConverterHelper
    {
        private static readonly Dictionary<Type, Func<JsonReader, object?>> _typeReaders = new (Type Type, Func<JsonReader, object?> Reader)[]
            {
                (typeof(bool), r => r.ReadAsBoolean()),
                (typeof(byte[]), r => r.ReadAsBytes()),
                (typeof(DateTime), r => r.ReadAsDateTime()),
                (typeof(DateTimeOffset), r => r.ReadAsDateTimeOffset()),
                (typeof(decimal), r => r.ReadAsDecimal()),
                (typeof(double), r => r.ReadAsDouble()),
                (typeof(int), r => r.ReadAsInt32()),
                (typeof(string), r => r.ReadAsString()),
            }
            .SelectMany(x => x.Type.IsClass
                ? new[] { x }
                : new[] { x, (Type: typeof(Nullable<>).MakeGenericType(x.Type), x.Reader) })
            .ToDictionary(x => x.Type, x => x.Reader);

        public static string IdToken => "$id";

        public static string RefToken => "$ref";

        public static bool IsCollection(this TypeInfo? type)
        {
            if (type is null)
            {
                return false;
            }

            if (type.IsArray && type.ToType() != typeof(byte[]))
            {
                return true;
            }

            if (type.IsGenericType && type.ToType().GetGenericTypeDefinition() == typeof(List<>))
            {
                return true;
            }

            return false;
        }

        public static JsonSerializationException CreateException(this JsonReader reader, string message)
            => reader.CheckNotNull(nameof(reader)) is IJsonLineInfo lineInfo && lineInfo.HasLineInfo()
            ? new JsonSerializationException(message, reader.Path, lineInfo.LineNumber, lineInfo.LinePosition, null)
            : new JsonSerializationException(message);

        public static void Advance(this JsonReader reader, string? errorMessage = null)
        {
            reader.CheckNotNull(nameof(reader));
            if (!reader.CheckNotNull(nameof(reader)).Read())
            {
                throw reader.CreateException(errorMessage ?? "Unexpected token structure.");
            }
        }

        public static void AssertProperty(this JsonReader reader, string propertyName, bool advance = true)
        {
            reader.CheckNotNull(nameof(reader));
            if (advance)
            {
                reader.Advance();
            }

            if (!IsProperty(reader, propertyName))
            {
                throw reader.CreateException($"Expected token '{propertyName}'.");
            }
        }

        public static T? Read<T>(this JsonReader reader, JsonSerializer serializer)
            => reader.CheckNotNull(nameof(reader)).TryRead(serializer, out T? result)
            ? result
            : throw reader.CreateException("Unexpected token structure.");

        public static object? Read(this JsonReader reader, TypeInfo? type, JsonSerializer serializer)
            => reader.CheckNotNull(nameof(reader)).Read(type.MapTypeInfo(), serializer);

        public static object? Read(this JsonReader reader, Type? type, JsonSerializer serializer)
            => reader.CheckNotNull(nameof(reader)).TryRead(type, serializer, out object? result)
            ? result
            : throw reader.CreateException("Unexpected token structure.");

        public static bool TryRead<T>(this JsonReader reader, JsonSerializer serializer, out T? value)
        {
            var result = TryRead(reader, typeof(T), serializer, out var v);
            value = result && v is T x ? x : default;
            return result;
        }

        public static bool TryRead(this JsonReader reader, TypeInfo? type, JsonSerializer serializer, out object? result)
            => reader.TryRead(type.MapTypeInfo(), serializer, out result);

        public static bool TryRead(this JsonReader reader, Type? type, JsonSerializer serializer, out object? result)
        {
            reader.CheckNotNull(nameof(reader));
            serializer.CheckNotNull(nameof(serializer));

            if (type is not null && _typeReaders.TryGetValue(type, out var read))
            {
                result = read(reader);
                return reader.TokenType != JsonToken.EndArray
                    && reader.TokenType != JsonToken.EndObject;
            }

            reader.Advance($"Expected token object of type '{type}'.");

            switch (reader.TokenType)
            {
                case JsonToken.String:
                    if (type != typeof(TypeInfo))
                    {
                        var text = reader.Value as string;
                        result = type == typeof(char) && text?.Length > 0
                            ? text[0]
                            : text;
                        return true;
                    }

                    break;

                case JsonToken.Null:
                    result = default;
                    return true;

                case JsonToken.EndArray:
                case JsonToken.EndObject:
                    result = default;
                    return false;
            }

            result = serializer.Deserialize(reader, type);
            return true;
        }

        public static void AssertStartObject(this JsonReader reader, bool advance = true)
        {
            reader.CheckNotNull(nameof(reader));
            if (advance && !reader.Read())
            {
                throw reader.CreateException($"Expected start object.");
            }

            if (reader.TokenType != JsonToken.StartObject)
{'fraction_non_alphanumeric': 0.10247851122423433, 'fraction_numerical': 0.0006676124509722107, 'mean_word_length': 1.765751211631664, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7318472', 'n_tokens_mistral': 2937, 'n_tokens_neox': 2812, 'n_words': 746}