Skip to content

Commit 42d7ef6

Browse files
committed
add AssetTypeValueIterator, letting us skip reading fields we don't care about
1 parent c0ac6af commit 42d7ef6

3 files changed

Lines changed: 424 additions & 93 deletions

File tree

AssetTools.NET/Standard/AssetTypeClass/AssetTypeTemplateField.cs

Lines changed: 122 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections.Generic;
44
using System.Linq;
5+
using System.Runtime.CompilerServices;
56

67
namespace AssetsTools.NET
78
{
@@ -255,108 +256,136 @@ public AssetTypeValueField ReadType(AssetsFileReader reader, AssetTypeValueField
255256
}
256257
else
257258
{
258-
if (type == AssetValueType.String)
259+
ReadPrimitiveType(reader, valueField, type, refMan);
260+
}
261+
262+
}
263+
return valueField;
264+
}
265+
266+
/// <summary>
267+
/// Deserialize a single primtive field and its children.
268+
/// This method only works for strings, numbers, and ManagedReferencesRegistry.
269+
/// </summary>
270+
/// <param name="reader">The reader to use.</param>
271+
/// <param name="valueField">The empty base value field to use.</param>
272+
/// <param name="type">The value type of the template field.</param>
273+
/// <param name="refMan">The ref type manager to use, if reading a MonoBehaviour using a ref type.</param>
274+
/// <returns>The deserialized base field.</returns>
275+
#if NETSTANDARD2_0_OR_GREATER
276+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
277+
#endif
278+
public void ReadPrimitiveType(AssetsFileReader reader, AssetTypeValueField valueField, AssetValueType type, RefTypeManager refMan)
279+
{
280+
if (type == AssetValueType.String)
281+
{
282+
valueField.Children = new List<AssetTypeValueField>(0);
283+
int length = reader.ReadInt32();
284+
valueField.Value = new AssetTypeValue(reader.ReadBytes(length), true);
285+
reader.Align();
286+
}
287+
else if (type == AssetValueType.ManagedReferencesRegistry)
288+
{
289+
ReadManagedReferencesRegistryType(reader, valueField, refMan);
290+
}
291+
else
292+
{
293+
int childCount = valueField.TemplateField.Children.Count;
294+
if (childCount == 0)
295+
{
296+
valueField.Children = new List<AssetTypeValueField>(0);
297+
switch (type)
259298
{
260-
valueField.Children = new List<AssetTypeValueField>(0);
261-
int length = reader.ReadInt32();
262-
valueField.Value = new AssetTypeValue(reader.ReadBytes(length), true);
263-
reader.Align();
299+
case AssetValueType.Int8:
300+
valueField.Value = new AssetTypeValue(reader.ReadSByte());
301+
break;
302+
case AssetValueType.UInt8:
303+
valueField.Value = new AssetTypeValue(reader.ReadByte());
304+
break;
305+
case AssetValueType.Bool:
306+
valueField.Value = new AssetTypeValue(reader.ReadBoolean());
307+
break;
308+
case AssetValueType.Int16:
309+
valueField.Value = new AssetTypeValue(reader.ReadInt16());
310+
break;
311+
case AssetValueType.UInt16:
312+
valueField.Value = new AssetTypeValue(reader.ReadUInt16());
313+
break;
314+
case AssetValueType.Int32:
315+
valueField.Value = new AssetTypeValue(reader.ReadInt32());
316+
break;
317+
case AssetValueType.UInt32:
318+
valueField.Value = new AssetTypeValue(reader.ReadUInt32());
319+
break;
320+
case AssetValueType.Int64:
321+
valueField.Value = new AssetTypeValue(reader.ReadInt64());
322+
break;
323+
case AssetValueType.UInt64:
324+
valueField.Value = new AssetTypeValue(reader.ReadUInt64());
325+
break;
326+
case AssetValueType.Float:
327+
valueField.Value = new AssetTypeValue(reader.ReadSingle());
328+
break;
329+
case AssetValueType.Double:
330+
valueField.Value = new AssetTypeValue(reader.ReadDouble());
331+
break;
264332
}
265-
else if (type == AssetValueType.ManagedReferencesRegistry)
266-
{
267-
// todo: error handling like in array
268-
if (refMan == null)
269-
throw new Exception("refMan MUST be set to deserialize objects with ref types!");
270333

271-
valueField.Children = new List<AssetTypeValueField>(0);
272-
ManagedReferencesRegistry registry = new ManagedReferencesRegistry();
273-
valueField.Value = new AssetTypeValue(registry);
274-
int registryChildCount = valueField.TemplateField.Children.Count;
275-
if (registryChildCount != 2)
276-
throw new Exception($"Expected ManagedReferencesRegistry to have two children, found {registryChildCount} instead!");
334+
if (valueField.TemplateField.IsAligned)
335+
reader.Align();
336+
}
337+
else if (type != AssetValueType.None)
338+
{
339+
throw new Exception("Cannot read value of field with children!");
340+
}
341+
}
342+
}
343+
344+
/// <summary>
345+
/// Deserialize a ManagedReferencesRegistry field.
346+
/// </summary>
347+
/// <param name="reader">The reader to use.</param>
348+
/// <param name="valueField">The empty base value field to use.</param>
349+
/// <param name="refMan">The ref type manager to use, if reading a MonoBehaviour using a ref type.</param>
350+
/// <returns>The deserialized base field.</returns>
351+
public void ReadManagedReferencesRegistryType(AssetsFileReader reader, AssetTypeValueField valueField, RefTypeManager refMan)
352+
{
353+
if (refMan == null)
354+
throw new Exception($"{nameof(refMan)} must be non-null to deserialize objects with ref types.");
355+
356+
valueField.Children = new List<AssetTypeValueField>(0);
357+
ManagedReferencesRegistry registry = new ManagedReferencesRegistry();
358+
valueField.Value = new AssetTypeValue(registry);
359+
int registryChildCount = valueField.TemplateField.Children.Count;
360+
if (registryChildCount != 2)
361+
throw new Exception($"Expected ManagedReferencesRegistry to have two children, found {registryChildCount} instead!");
277362

278-
registry.version = reader.ReadInt32();
279-
registry.references = new List<AssetTypeReferencedObject>();
363+
registry.version = reader.ReadInt32();
364+
registry.references = new List<AssetTypeReferencedObject>();
280365

281-
if (registry.version == 1)
282-
{
283-
while (true)
284-
{
285-
// rid is consecutive starting at 0
286-
var refdObject = MakeReferencedObject(reader, registry.version, registry.references.Count, refMan);
287-
if (refdObject.type.Equals(AssetTypeReference.TERMINUS))
288-
{
289-
break;
290-
}
291-
registry.references.Add(refdObject);
292-
}
293-
}
294-
else
295-
{
296-
int childCount = reader.ReadInt32();
297-
for (int i = 0; i < childCount; i++)
298-
{
299-
// rid is read from data
300-
var refdObject = MakeReferencedObject(reader, registry.version, -1, refMan);
301-
registry.references.Add(refdObject);
302-
}
303-
}
304-
}
305-
else
366+
if (registry.version == 1)
367+
{
368+
while (true)
369+
{
370+
// rid is consecutive starting at 0
371+
var refdObject = MakeReferencedObject(reader, registry.version, registry.references.Count, refMan);
372+
if (refdObject.type.Equals(AssetTypeReference.TERMINUS))
306373
{
307-
int childCount = valueField.TemplateField.Children.Count;
308-
if (childCount == 0)
309-
{
310-
valueField.Children = new List<AssetTypeValueField>(0);
311-
switch (valueField.TemplateField.ValueType)
312-
{
313-
case AssetValueType.Int8:
314-
valueField.Value = new AssetTypeValue(reader.ReadSByte());
315-
break;
316-
case AssetValueType.UInt8:
317-
valueField.Value = new AssetTypeValue(reader.ReadByte());
318-
break;
319-
case AssetValueType.Bool:
320-
valueField.Value = new AssetTypeValue(reader.ReadBoolean());
321-
break;
322-
case AssetValueType.Int16:
323-
valueField.Value = new AssetTypeValue(reader.ReadInt16());
324-
break;
325-
case AssetValueType.UInt16:
326-
valueField.Value = new AssetTypeValue(reader.ReadUInt16());
327-
break;
328-
case AssetValueType.Int32:
329-
valueField.Value = new AssetTypeValue(reader.ReadInt32());
330-
break;
331-
case AssetValueType.UInt32:
332-
valueField.Value = new AssetTypeValue(reader.ReadUInt32());
333-
break;
334-
case AssetValueType.Int64:
335-
valueField.Value = new AssetTypeValue(reader.ReadInt64());
336-
break;
337-
case AssetValueType.UInt64:
338-
valueField.Value = new AssetTypeValue(reader.ReadUInt64());
339-
break;
340-
case AssetValueType.Float:
341-
valueField.Value = new AssetTypeValue(reader.ReadSingle());
342-
break;
343-
case AssetValueType.Double:
344-
valueField.Value = new AssetTypeValue(reader.ReadDouble());
345-
break;
346-
}
347-
348-
if (valueField.TemplateField.IsAligned)
349-
reader.Align();
350-
}
351-
else if (valueField.TemplateField.ValueType != AssetValueType.None)
352-
{
353-
throw new Exception("Cannot read value of field with children!");
354-
}
374+
break;
355375
}
376+
registry.references.Add(refdObject);
377+
}
378+
}
379+
else
380+
{
381+
int childCount = reader.ReadInt32();
382+
for (int i = 0; i < childCount; i++)
383+
{
384+
// rid is read from data
385+
var refdObject = MakeReferencedObject(reader, registry.version, -1, refMan);
386+
registry.references.Add(refdObject);
356387
}
357-
358388
}
359-
return valueField;
360389
}
361390

362391
public AssetTypeTemplateField this[string name]

0 commit comments

Comments
 (0)