/// <summary> /// 정의를 하나 읽습니다. /// 정의는 스키마 또는 ENUM 테이블 정의입니다. /// </summary> /// <param name="reader">reader</param> /// <param name="defFile">정의 파일</param> private static void ReadDefinition(ref Utf8JsonReader reader, ref DefinitionFile defFile) { if (reader.TokenType != JsonTokenType.StartObject) { throw new Exception("An internal error has occured. Definition token must starts a StartObject token"); } if (!reader.Read() && reader.TokenType != JsonTokenType.PropertyName) { throw new ArgumentException("An invalid definition has detected"); } string firstPropName = reader.GetString(); if (firstPropName.StartsWith("enum ")) { reader.Read(); Match match = EnumDefRegex.Match(firstPropName); if (!match.Success) { throw new ArgumentException($"{firstPropName} is an invalid enum definition"); } GroupCollection groups = match.Groups; string enumName = groups["name"].Value.Trim(); if (!NameRegex.IsMatch(enumName)) { throw MakeDisallowedNameException(enumName, "enum name"); } FieldType enumValueType = FieldType.Nil; if (groups["type"].Success) { Field valueField = new Field(); BuildFieldType(ref valueField, groups["type"].Value); enumValueType = valueField.Type; } string enumDesc = string.Empty; if (firstPropName.IndexOf("//", match.Length) != -1) { enumDesc = firstPropName.Substring(firstPropName.IndexOf("//") + 2).Trim(); } Table enumTable = ReadEnumTable(ref reader, enumName, enumValueType); if (!string.IsNullOrWhiteSpace(enumDesc)) { enumTable.Schema.Description = enumDesc; } if (!defFile.AddEnumTable(enumTable)) { throw new ArgumentException($"{enumName} is an already defined definition"); } } else { Schema schema = new Schema(); bool hasPartial = false; while (reader.TokenType != JsonTokenType.EndObject) { string propName = reader.GetString(); reader.Read(); switch (propName) { case "name": { schema.Name = reader.GetString().Trim(); if (!NameRegex.IsMatch(schema.Name)) { throw MakeDisallowedNameException(schema.Name, "schema name"); } reader.Read(); break; } case "fields": { if (reader.TokenType == JsonTokenType.StartObject) { reader.Read(); while (reader.TokenType != JsonTokenType.EndObject) { string name = reader.GetString().Trim(); if (!NameRegex.IsMatch(name)) { throw MakeDisallowedNameException(schema.Name, "field name"); } reader.Read(); Field field = ReadField(ref reader, name); if (!schema.AddField(field)) { throw new ArgumentException($"{name} is an already defined field name"); } } reader.Read(); } break; } case "partials": case "parts": { hasPartial = true; foreach (string name in reader.ReadStringList()) { if (!PartialNameRegex.IsMatch(name)) { throw MakeDisallowedNameException(schema.Name, "partial name"); } if (!schema.AddPartial(name)) { throw new ArgumentException($"{name} is an already defiend partial name"); } } break; } case "embed": { schema.Embed = reader.GetBoolean(); reader.Read(); break; } case "desc": case "description": { schema.Description = reader.GetString(); reader.Read(); break; } default: { reader.Skip(); // Skip을 하면 StartToken에서 EndToken으로 가게 되므로, // 한번 더 Read해서 Token을 완전히 끝냄 reader.Read(); break; } } } if (!hasPartial) { schema.AddPartial(schema.Name); } if (!defFile.AddSchema(schema)) { throw new Exception($"{schema.Name} is an already defiend schema name"); } } reader.Read(); }