Attribute -> RbxAttribute

This commit is contained in:
Max
2021-06-05 17:21:12 -05:00
parent 71cd85513e
commit 5dc65e2184
23 changed files with 76 additions and 133 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
namespace RobloxFiles
@ -45,7 +46,7 @@ namespace RobloxFiles
// Region3int16 = 32
}
public class Attribute : IDisposable
public class RbxAttribute : IDisposable
{
private static readonly IReadOnlyDictionary<AttributeType, Tokenizer> AttributeSupport;
private static readonly IReadOnlyDictionary<Type, AttributeType> SupportedTypes;
@ -70,20 +71,20 @@ namespace RobloxFiles
Writer = support.GetMethod("WriteAttribute");
}
public object ReadAttribute(Attribute attr)
public object ReadAttribute(RbxAttribute attr)
{
var args = new object[1] { attr };
return Reader.Invoke(Token, args);
}
public void WriteAttribute(Attribute attr, object value)
public void WriteAttribute(RbxAttribute attr, object value)
{
var args = new object[2] { attr, value };
Writer.Invoke(Token, args);
}
}
static Attribute()
static RbxAttribute()
{
var attributeSupport = new Dictionary<AttributeType, Tokenizer>();
var supportedTypes = new Dictionary<Type, AttributeType>();
@ -193,19 +194,19 @@ namespace RobloxFiles
Writer = null;
}
internal Attribute(BinaryReader reader)
internal RbxAttribute(BinaryReader reader)
{
Reader = reader;
Read();
}
internal Attribute(MemoryStream stream)
internal RbxAttribute(MemoryStream stream)
{
Reader = new BinaryReader(stream);
Read();
}
internal Attribute(object value)
internal RbxAttribute(object value)
{
Type type = value.GetType();
@ -217,44 +218,31 @@ namespace RobloxFiles
}
}
public class Attributes : SortedDictionary<string, Attribute>
public class RbxAttributes : SortedDictionary<string, RbxAttribute>
{
private void Initialize(BinaryReader reader)
internal void Load(byte[] buffer)
{
Stream stream = reader.BaseStream;
Clear();
if (stream.Length - stream.Position < 4)
if (buffer == null || buffer.Length < 4)
// Not enough room to read the entry count, possibly empty?
return;
int numEntries = reader.ReadInt32();
for (int i = 0; i < numEntries; i++)
using (var input = new MemoryStream(buffer))
using (var reader = new BinaryReader(input))
{
string key = reader.ReadString(true);
var attribute = new Attribute(reader);
Add(key, attribute);
int numEntries = reader.ReadInt32();
for (int i = 0; i < numEntries; i++)
{
string key = reader.ReadString(true);
var attribute = new RbxAttribute(reader);
Add(key, attribute);
}
}
}
public Attributes() : base()
{
}
internal Attributes(BinaryReader reader)
{
Initialize(reader);
}
internal Attributes(MemoryStream stream)
{
using (var reader = new BinaryReader(stream))
Initialize(reader);
stream.Dispose();
}
internal byte[] Serialize()
internal byte[] Save()
{
if (Count == 0)
return Array.Empty<byte>();

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
@ -61,26 +59,16 @@ namespace RobloxFiles
public bool Destroyed { get; internal set; }
/// <summary>A hashset of CollectionService tags assigned to this Instance.</summary>
public HashSet<string> Tags { get; } = new HashSet<string>();
public readonly HashSet<string> Tags = new HashSet<string>();
/// <summary>The attributes defined for this Instance.</summary>
private Attributes AttributesImpl = new Attributes();
/// <summary>The public readonly access point of the attributes on this Instance.</summary>
public IReadOnlyDictionary<string, Attribute> Attributes => AttributesImpl;
public readonly RbxAttributes Attributes = new RbxAttributes();
/// <summary>The internal serialized data of this Instance's attributes</summary>
internal byte[] AttributesSerialize
{
get
{
return AttributesImpl?.Serialize() ?? Array.Empty<byte>();
}
set
{
var data = new MemoryStream(value);
AttributesImpl = new Attributes(data);
}
get => Attributes.Save();
set => Attributes.Load(value);
}
/// <summary>
@ -134,7 +122,7 @@ namespace RobloxFiles
/// <returns>True if the attribute could be read and the out value was set, false otherwise.</returns>
public bool GetAttribute<T>(string key, out T value)
{
if (AttributesImpl.TryGetValue(key, out Attribute attr))
if (Attributes.TryGetValue(key, out RbxAttribute attr))
{
if (attr.Value is T result)
{
@ -161,13 +149,16 @@ namespace RobloxFiles
if (key.Length > 100)
return false;
Type type = value.GetType();
if (!Attribute.SupportsType(type))
if (key.StartsWith("RBX", StringComparison.InvariantCulture))
return false;
var attr = new Attribute(value);
AttributesImpl[key] = attr;
Type type = value.GetType();
if (!RbxAttribute.SupportsType(type))
return false;
var attr = new RbxAttribute(value);
Attributes[key] = attr;
return true;
}
@ -474,8 +465,8 @@ namespace RobloxFiles
Parent = null;
ParentLocked = true;
Tags?.Clear();
AttributesImpl?.Clear();
Tags.Clear();
Attributes.Clear();
while (Children.Any())
{