private static async Task ProcessUnihanNumericValues(IDataSource unihanDataSource, UnicodeInfoBuilder builder)
        {
            using (var reader = new UnihanDataFileReader(await unihanDataSource.OpenDataFileAsync(UnihanNumericValuesFileName).ConfigureAwait(false)))
            {
                while (reader.Read())
                {
                    var entry = builder.GetUnihan(reader.CodePoint);

                    switch (reader.PropertyName)
                    {
                    case UnihanProperty.kAccountingNumeric:
                        entry.NumericType = UnihanNumericType.Accounting;
                        break;

                    case UnihanProperty.kOtherNumeric:
                        entry.NumericType = UnihanNumericType.Other;
                        break;

                    case UnihanProperty.kPrimaryNumeric:
                        entry.NumericType = UnihanNumericType.Primary;
                        break;

                    default:
                        throw new InvalidDataException("Unrecognized property name: " + reader.PropertyName + ".");
                    }

                    entry.NumericValue = long.Parse(reader.PropertyValue);
                }
            }
        }
        private static async Task ProcessUnihanIrgSources(IDataSource unihanDataSource, UnicodeInfoBuilder builder)
        {
            using (var reader = new UnihanDataFileReader(await unihanDataSource.OpenDataFileAsync(UnihanIrgSourcesFileName).ConfigureAwait(false)))
            {
                while (reader.Read())
                {
                    switch (reader.PropertyName)
                    {
                    case UnihanProperty.kRSUnicode:
                        var entry  = builder.GetUnihan(reader.CodePoint);
                        var values = reader.PropertyValue.Split(' ');

                        foreach (var value in values)
                        {
                            bool isSimplified = false;
                            int  index;

                            for (int i = 0; i < value.Length; ++i)
                            {
                                switch (value[i])
                                {
                                case '\'':
                                    isSimplified = true;
                                    goto case '.';

                                case '.':
                                    index = i;
                                    goto SeparatorFound;
                                }
                            }
                            throw new InvalidDataException("Failed to decode value for kRSUnicode / Unicode_Radical_Stroke.");

                            SeparatorFound :;
                            entry.UnicodeRadicalStrokeCounts.Add(new UnicodeRadicalStrokeCount(byte.Parse(value.Substring(0, index), NumberStyles.None), sbyte.Parse(value.Substring(index + (isSimplified ? 2 : 1)), NumberStyles.AllowLeadingSign), isSimplified));
                        }
                        break;

                    default:
                        // Ignore unhandled properties for now.
                        break;
                    }
                }
            }
        }
        private static async Task ProcessUnihanVariants(IDataSource unihanDataSource, UnicodeInfoBuilder builder)
        {
            using (var reader = new UnihanDataFileReader(await unihanDataSource.OpenDataFileAsync(UnihanVariantsFileName).ConfigureAwait(false)))
            {
                while (reader.Read())
                {
                    // This statement is used to skip unhandled properties entirely.
                    switch (reader.PropertyName)
                    {
                    case UnihanProperty.kSimplifiedVariant:
                    case UnihanProperty.kTraditionalVariant:
                        break;

                    default:
                        // Ignore unhandled properties for now.
                        continue;
                    }

                    var entry = builder.GetUnihan(reader.CodePoint);

                    switch (reader.PropertyName)
                    {
                    case UnihanProperty.kSimplifiedVariant:
                        entry.SimplifiedVariant = char.ConvertFromUtf32(HexCodePoint.ParsePrefixed(reader.PropertyValue));
                        break;

                    case UnihanProperty.kTraditionalVariant:
                        entry.TraditionalVariant = char.ConvertFromUtf32(HexCodePoint.ParsePrefixed(reader.PropertyValue));
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
            }
        }
        private static async Task ProcessUnihanReadings(IDataSource unihanDataSource, UnicodeInfoBuilder builder)
        {
            using (var reader = new UnihanDataFileReader(await unihanDataSource.OpenDataFileAsync(UnihanReadingsFileName).ConfigureAwait(false)))
            {
                while (reader.Read())
                {
                    // This statement is used to skip unhandled properties entirely.
                    switch (reader.PropertyName)
                    {
                    case UnihanProperty.kDefinition:
                    case UnihanProperty.kMandarin:
                    case UnihanProperty.kCantonese:
                    case UnihanProperty.kJapaneseKun:
                    case UnihanProperty.kJapaneseOn:
                    case UnihanProperty.kKorean:
                    case UnihanProperty.kHangul:
                    case UnihanProperty.kVietnamese:
                        break;

                    default:
                        // Ignore unhandled properties for now.
                        continue;
                    }

                    // This entry will only be created if there is meaningful data.
                    var entry = builder.GetUnihan(reader.CodePoint);

                    switch (reader.PropertyName)
                    {
                    case UnihanProperty.kDefinition:
                        entry.Definition = reader.PropertyValue;
                        break;

                    case UnihanProperty.kMandarin:
                        entry.MandarinReading = reader.PropertyValue;
                        break;

                    case UnihanProperty.kCantonese:
                        entry.CantoneseReading = reader.PropertyValue;
                        break;

                    case UnihanProperty.kJapaneseKun:
                        entry.JapaneseKunReading = reader.PropertyValue;
                        break;

                    case UnihanProperty.kJapaneseOn:
                        entry.JapaneseOnReading = reader.PropertyValue;
                        break;

                    case UnihanProperty.kKorean:
                        entry.KoreanReading = reader.PropertyValue;
                        break;

                    case UnihanProperty.kHangul:
                        entry.HangulReading = reader.PropertyValue;
                        break;

                    case UnihanProperty.kVietnamese:
                        entry.VietnameseReading = reader.PropertyValue;
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
            }
        }