using System; using System.Xml; namespace Oni.Metadata { internal class MetaEnum : MetaType { private MetaType baseType; private Type enumType; public MetaEnum(MetaType baseType, Type enumType) : base("Enum", baseType.Size) { if (baseType != MetaType.Byte && baseType != MetaType.Int16 && baseType != MetaType.UInt16 && baseType != MetaType.Int32 && baseType != MetaType.UInt32 && baseType != MetaType.Int64 && baseType != MetaType.UInt64) { throw new ArgumentException("Invalid enum base type", "baseType"); } this.baseType = baseType; this.enumType = enumType; } public MetaType BaseType => baseType; public Type EnumType => enumType; public bool IsFlags => Utils.IsFlagsEnum(enumType); protected override bool IsLeafImpl() => true; public override void Accept(IMetaTypeVisitor visitor) => visitor.VisitEnum(this); public void BinaryToXml(BinaryReader reader, XmlWriter writer) { object value; if (baseType == MetaType.Byte) value = System.Enum.ToObject(enumType, reader.ReadByte()); else if (baseType == MetaType.Int16) value = System.Enum.ToObject(enumType, reader.ReadInt16()); else if (baseType == MetaType.UInt16) value = System.Enum.ToObject(enumType, reader.ReadUInt16()); else if (baseType == MetaType.Int32) value = System.Enum.ToObject(enumType, reader.ReadInt32()); else if (baseType == MetaType.UInt32) value = System.Enum.ToObject(enumType, reader.ReadUInt32()); else if (baseType == MetaType.Int64) value = System.Enum.ToObject(enumType, reader.ReadInt64()); else value = System.Enum.ToObject(enumType, reader.ReadUInt64()); string text = value.ToString().Replace(",", string.Empty); if (text == "None" && IsFlags) text = string.Empty; writer.WriteValue(text); } public void XmlToBinary(XmlReader reader, BinaryWriter writer) { string text = reader.ReadElementContentAsString(); if (string.IsNullOrEmpty(text) && IsFlags) { if (baseType == MetaType.Byte) writer.WriteByte(0); else if (baseType == MetaType.Int16 || baseType == MetaType.UInt16) writer.WriteUInt16(0); else if (baseType == MetaType.Int32 || baseType == MetaType.UInt32) writer.Write(0); else writer.Write(0L); return; } object value = null; try { value = System.Enum.Parse(enumType, text.Trim().Replace(' ', ',')); } catch { } if (value == null) throw new FormatException(string.Format("{0} is not a valid value name. Run onisplit -help enums to see a list of possible names.", text)); if (baseType == MetaType.Byte) writer.WriteByte(Convert.ToByte(value)); else if (baseType == MetaType.Int16) writer.Write(Convert.ToInt16(value)); else if (baseType == MetaType.UInt16) writer.Write(Convert.ToUInt16(value)); else if (baseType == MetaType.Int32) writer.Write(Convert.ToInt32(value)); else if (baseType == MetaType.UInt32) writer.Write(Convert.ToUInt32(value)); else if (baseType == MetaType.Int64) writer.Write(Convert.ToInt64(value)); else writer.Write(Convert.ToUInt64(value)); } public static T Parse(string text) where T : struct { object value = null; if (string.IsNullOrEmpty(text) && Utils.IsFlagsEnum(typeof(T))) { value = System.Enum.Parse(typeof(T), "None"); } else { try { string[] values = text.Split(new char[0], StringSplitOptions.RemoveEmptyEntries); text = string.Join(", ", values); value = System.Enum.Parse(typeof(T), text, true); } catch { } } if (value == null) throw new FormatException(string.Format("{0} is not a valid value name. Run onisplit -help enums to see a list of possible names.", text)); return (T)value; } public static string ToString(T value) where T : struct { string text = value.ToString().Replace(",", string.Empty); if (text == "None" && Utils.IsFlagsEnum(typeof(T))) text = string.Empty; return text; } } }