This commit is contained in:
Даниил Заикин
2026-06-17 20:44:53 +03:00
parent 9d153773c2
commit b133e7c656
1880 changed files with 244545 additions and 0 deletions
@@ -0,0 +1,29 @@
using System;
using System.Collections;
namespace QFSW.QC.Parsers
{
public class ArrayParser : IQcParser
{
public int Priority => -100;
public bool CanParse(Type type)
{
return type.IsArray;
}
public object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
{
Type elementType = type.GetElementType();
string[] valueParts = value.ReduceScope('[', ']').SplitScoped(',');
IList dataArray = Array.CreateInstance(elementType, valueParts.Length);
for (int i = 0; i < valueParts.Length; i++)
{
dataArray[i] = recursiveParser(valueParts[i], elementType);
}
return dataArray;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: debc47c083b042c4c8a295d533a85094
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,22 @@
namespace QFSW.QC.Parsers
{
public class BoolParser : BasicCachedQcParser<bool>
{
public override bool Parse(string value)
{
value = value.ToLower().Trim();
switch (value)
{
case "true": return true;
case "on": return true;
case "1": return true;
case "yes": return true;
case "false": return false;
case "off": return false;
case "0": return false;
case "no": return false;
default: throw new ParserInputException($"Cannot parse '{value}' to a bool.");
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f610c84a8ec2129489d0f4d00a585b18
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,28 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace QFSW.QC.Parsers
{
public class CollectionParser : MassGenericQcParser
{
protected override HashSet<Type> GenericTypes { get; } = new HashSet<Type>
{
typeof(List<>),
typeof(Stack<>),
typeof(Queue<>),
typeof(HashSet<>),
typeof(LinkedList<>),
typeof(ConcurrentStack<>),
typeof(ConcurrentQueue<>),
typeof(ConcurrentBag<>)
};
public override object Parse(string value, Type type)
{
Type arrayType = type.GetGenericArguments()[0].MakeArrayType();
object array = ParseRecursive(value, arrayType);
return Activator.CreateInstance(type, array);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2692eedbcfd50e24a8644b39e70351a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class ColorParser : BasicCachedQcParser<Color>
{
private readonly Dictionary<string, Color> _colorLookup;
public ColorParser()
{
_colorLookup = new Dictionary<string, Color>();
PropertyInfo[] colorProperties = typeof(Color).GetProperties(BindingFlags.Static | BindingFlags.Public);
foreach (PropertyInfo prop in colorProperties)
{
if (prop.CanRead && !prop.CanWrite)
{
MethodInfo propReader = prop.GetMethod;
if (propReader.ReturnType == typeof(Color))
{
_colorLookup.Add(prop.Name, (Color)propReader.Invoke(null, Array.Empty<object>()));
}
}
}
}
public override Color Parse(string value)
{
if (_colorLookup.ContainsKey(value.ToLower()))
{
return _colorLookup[value.ToLower()];
}
try
{
if (value.StartsWith("0x"))
{
return ParseHexColor(value);
}
else
{
return ParseRGBAColor(value);
}
}
catch (FormatException e)
{
throw new ParserInputException($"{e.Message}\nThe format must be either of:" +
$"\n - R,G,B" +
$"\n - R,G,B,A" +
$"\n - 0xRRGGBB" +
$"\n - 0xRRGGBBAA" +
$"\n - A preset color such as 'red'", e);
}
}
private Color ParseRGBAColor(string value)
{
string[] colorParts = value.Split(',');
Color parsedColor = Color.white;
int i = 0;
if (colorParts.Length < 3 || colorParts.Length > 4) { throw new FormatException($"Cannot parse '{value}' as a Color."); }
float ParsePart(string part)
{
float val = float.Parse(part);
if (val < 0 || val > 1) { throw new FormatException($"{val} falls outside of the valid [0,1] range for a component of a Color."); }
return val;
}
try
{
for (; i < colorParts.Length; i++)
{
parsedColor[i] = ParsePart(colorParts[i]);
}
return parsedColor;
}
catch (FormatException)
{
throw new FormatException($"Cannot parse '{colorParts[i]}' as part of a Color, it must be numerical and in the valid range [0,1].");
}
}
private Color ParseHexColor(string value)
{
int digitCount = value.Length - 2;
if (digitCount != 6 && digitCount != 8)
{
throw new FormatException("Hex colors must contain either 6 or 8 hex digits.");
}
Color parsedColor = Color.white;
int byteCount = digitCount / 2;
int i = 0;
try
{
for (; i < byteCount; i++)
{
parsedColor[i] = int.Parse(value.Substring(2 * (1 + i), 2), System.Globalization.NumberStyles.HexNumber) / 255f;
}
return parsedColor;
}
catch (FormatException)
{
throw new FormatException($"Cannot parse '{value.Substring(2 * (1 + i), 2)}' as part of a Color as it was invalid hex.");
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 31739988d804da941aa363d4a58bfae6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,22 @@
using QFSW.QC.Utilities;
using System;
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class ComponentParser : PolymorphicQcParser<Component>
{
public override Component Parse(string value, Type type)
{
GameObject obj = ParseRecursive<GameObject>(value);
Component objComponent = obj.GetComponent(type);
if (!objComponent)
{
throw new ParserInputException($"No component on the object '{value}' of type {type.GetDisplayName()} existed.");
}
return objComponent;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4fbd8b9265a0c3f4a9a3aa55595b889f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
using QFSW.QC.Utilities;
using System;
namespace QFSW.QC.Parsers
{
public class EnumParser : PolymorphicCachedQcParser<Enum>
{
public override Enum Parse(string value, Type type)
{
try
{
return (Enum)Enum.Parse(type, value);
}
catch (Exception e)
{
throw new ParserInputException($"Cannot parse '{value}' to the type '{type.GetDisplayName()}'. To see the supported values, use the command `enum-info {type}`", e);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e211a4d691805e049a06ba8a06ca4f92
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace QFSW.QC.Parsers
{
public class EnumerableParser : MassGenericQcParser
{
protected override HashSet<Type> GenericTypes { get; } = new HashSet<Type>()
{
typeof(IEnumerable<>),
typeof(ICollection<>),
typeof(IReadOnlyCollection<>),
typeof(IList<>),
typeof(IReadOnlyList<>)
};
public override object Parse(string value, Type type)
{
Type arrayType = type.GetGenericArguments()[0].MakeArrayType();
return ParseRecursive(value, arrayType);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c885a65409b41894ab2688fef15008b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
using QFSW.QC.Utilities;
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class GameObjectParser : BasicQcParser<GameObject>
{
public override GameObject Parse(string value)
{
string name = ParseRecursive<string>(value);
GameObject obj = GameObjectExtensions.Find(name, true);
if (!obj)
{
throw new ParserInputException($"Could not find GameObject of name {value}.");
}
return obj;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c5d24ea53ab5c341b04e2b935368e73
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
using System;
namespace QFSW.QC.Parsers
{
public class NullableParser : GenericQcParser
{
protected override Type GenericType => typeof(Nullable<>);
public override object Parse(string value, Type type)
{
if (value == "null")
{
return null;
}
Type innerType = type.GetGenericArguments()[0];
return ParseRecursive(value, innerType);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d756a2c71cd39bc469193330c26e8797
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,46 @@
using QFSW.QC.Utilities;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace QFSW.QC.Parsers
{
public class PrimitiveParser : IQcParser
{
private readonly HashSet<Type> _primitiveTypes = new HashSet<Type>
{
typeof(int),
typeof(float),
typeof(decimal),
typeof(double),
typeof(bool),
typeof(byte),
typeof(sbyte),
typeof(uint),
typeof(short),
typeof(ushort),
typeof(long),
typeof(ulong),
typeof(char)
};
public int Priority => -1000;
public bool CanParse(Type type)
{
return _primitiveTypes.Contains(type);
}
public object Parse(string value, Type type, Func<string, Type, object> recursiveParser)
{
try
{
return Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}
catch (FormatException e)
{
throw new ParserInputException($"Cannot parse '{value}' to the type '{type.GetDisplayName()}'.", e);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 030edeaf5882fc4408d3ebb9368779a9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,14 @@
{
"name": "QFSW.QC.Parsers",
"references": [
"QFSW.QC"
],
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a5d04fa5e431fa844be99e9199658b16
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,13 @@
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class QuaternionParser : BasicCachedQcParser<Quaternion>
{
public override Quaternion Parse(string value)
{
Vector4 vector = ParseRecursive<Vector4>(value);
return new Quaternion(vector.x, vector.y, vector.z, vector.w);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 99e9d99d8fb57ac42a9821372699449b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,14 @@
namespace QFSW.QC.Parsers
{
public class StringParser : BasicCachedQcParser<string>
{
public override int Priority => int.MaxValue;
public override string Parse(string value)
{
return value
.ReduceScope('"', '"')
.UnescapeText('"');
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 028f88c2880e54c4f883885b9a263c8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
namespace QFSW.QC.Parsers
{
public class TupleParser : MassGenericQcParser
{
private const int MaxFlatTupleSize = 8;
protected override HashSet<Type> GenericTypes { get; } = new HashSet<Type>
{
typeof(ValueTuple<>),
typeof(ValueTuple<,>),
typeof(ValueTuple<,,>),
typeof(ValueTuple<,,,>),
typeof(ValueTuple<,,,,>),
typeof(ValueTuple<,,,,,>),
typeof(ValueTuple<,,,,,,>),
typeof(ValueTuple<,,,,,,,>),
typeof(Tuple<>),
typeof(Tuple<,>),
typeof(Tuple<,,>),
typeof(Tuple<,,,>),
typeof(Tuple<,,,,>),
typeof(Tuple<,,,,,>),
typeof(Tuple<,,,,,,>),
typeof(Tuple<,,,,,,,>)
};
public override object Parse(string value, Type type)
{
TextProcessing.ScopedSplitOptions options = TextProcessing.ScopedSplitOptions.Default;
options.MaxCount = MaxFlatTupleSize;
string[] inputParts = value.ReduceScope('(', ')').SplitScoped(',', options);
Type[] elementTypes = type.GetGenericArguments();
if (elementTypes.Length != inputParts.Length)
{
throw new ParserInputException($"Desired tuple type {type} has {elementTypes.Length} elements but input contained {inputParts.Length}.");
}
object[] tupleParts = new object[inputParts.Length];
for (int i = 0; i < tupleParts.Length; i++)
{
tupleParts[i] = ParseRecursive(inputParts[i], elementTypes[i]);
}
return Activator.CreateInstance(type, tupleParts);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6842e4e236f2eaa41bddefbef8aa7276
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using System;
namespace QFSW.QC.Parsers
{
public class TypeParser : BasicCachedQcParser<Type>
{
public override Type Parse(string value)
{
return QuantumParser.ParseType(value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f7be70a556f9e094c8fa7f5dd0c7e81b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class Vector2IntParser : BasicCachedQcParser<Vector2Int>
{
public override Vector2Int Parse(string value)
{
return (Vector2Int)ParseRecursive<Vector3Int>(value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0288f6e4dbdbb964eb1f0f7bafe6ca37
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class Vector2Parser : BasicCachedQcParser<Vector2>
{
public override Vector2 Parse(string value)
{
return ParseRecursive<Vector4>(value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb12462fc0295f046957d1030894bea6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,33 @@
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class Vector3IntParser : BasicCachedQcParser<Vector3Int>
{
public override Vector3Int Parse(string value)
{
string[] vectorParts = value.Split(',');
Vector3Int parsedVector = new Vector3Int();
if (vectorParts.Length < 2 || vectorParts.Length > 3)
{
throw new ParserInputException($"Cannot parse '{value}' as an int vector, the format must be either x,y or x,y,z");
}
int i = 0;
try
{
for (; i < vectorParts.Length; i++)
{
parsedVector[i] = int.Parse(vectorParts[i]);
}
return parsedVector;
}
catch
{
throw new ParserInputException($"Cannot parse '{vectorParts[i]}' as it must be integral.");
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7af974e71f13d6c4f9c3a5291581e815
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class Vector3Parser : BasicCachedQcParser<Vector3>
{
public override Vector3 Parse(string value)
{
return ParseRecursive<Vector4>(value);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ca39e94d5f7e12b4cbb7b00f77a8278c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,25 @@
using UnityEngine;
namespace QFSW.QC.Parsers
{
public class Vector4Parser : BasicCachedQcParser<Vector4>
{
public override Vector4 Parse(string value)
{
string[] vectorParts = value.SplitScoped(',');
Vector4 parsedVector = new Vector4();
if (vectorParts.Length < 2 || vectorParts.Length > 4)
{
throw new ParserInputException($"Cannot parse '{value}' as a vector, the format must be either x,y x,y,z or x,y,z,w.");
}
for (int i = 0; i < vectorParts.Length; i++)
{
parsedVector[i] = ParseRecursive<float>(vectorParts[i]);
}
return parsedVector;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: feb6ca1c0ec89bf4e8bb8ae58737a1f3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: