using System; namespace Nanomesh { public unsafe interface IMetaAttribute { IMetaAttribute Set(int index, K value) where K : unmanaged; K Get(int index) where K : unmanaged; } public unsafe struct MetaAttribute : IMetaAttribute where T0 : unmanaged { public T0 attr0; public MetaAttribute(T0 attr0) { this.attr0 = attr0; } public unsafe K Get(int index) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; return kk[0]; } default: throw new ArgumentOutOfRangeException(); } } public IMetaAttribute Set(int index, K value) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; kk[0] = value; return this; } default: throw new ArgumentOutOfRangeException(); } } public override int GetHashCode() { return attr0.GetHashCode(); } public override bool Equals(object obj) { return ((MetaAttribute)obj).attr0.Equals(attr0); } } public unsafe struct MetaAttribute : IMetaAttribute where T0 : unmanaged where T1 : unmanaged { public T0 attr0; public T1 attr1; public MetaAttribute(T0 attr0, T1 attr1) { this.attr0 = attr0; this.attr1 = attr1; } public unsafe K Get(int index) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; return kk[0]; } case 1: fixed (T1* k = &attr1) { K* kk = (K*)k; return kk[0]; } default: throw new ArgumentOutOfRangeException(); } } public IMetaAttribute Set(int index, K value) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; kk[0] = value; return this; } case 1: fixed (T1* k = &attr1) { K* kk = (K*)k; kk[0] = value; return this; } default: throw new ArgumentOutOfRangeException(); } } } public unsafe struct MetaAttribute : IMetaAttribute where T0 : unmanaged where T1 : unmanaged where T2 : unmanaged { public T0 attr0; public T1 attr1; public T2 attr2; public MetaAttribute(T0 attr0, T1 attr1, T2 attr2) { this.attr0 = attr0; this.attr1 = attr1; this.attr2 = attr2; } public unsafe K Get(int index) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; return kk[0]; } case 1: fixed (T1* k = &attr1) { K* kk = (K*)k; return kk[0]; } case 2: fixed (T2* k = &attr2) { K* kk = (K*)k; return kk[0]; } default: throw new ArgumentOutOfRangeException(); } } public IMetaAttribute Set(int index, K value) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; kk[0] = value; return this; } case 1: fixed (T1* k = &attr1) { K* kk = (K*)k; kk[0] = value; return this; } case 2: fixed (T2* k = &attr2) { K* kk = (K*)k; kk[0] = value; return this; } default: throw new ArgumentOutOfRangeException(); } } } public unsafe struct MetaAttribute : IMetaAttribute where T0 : unmanaged where T1 : unmanaged where T2 : unmanaged where T3 : unmanaged { public T0 attr0; public T1 attr1; public T2 attr2; public T3 attr3; public MetaAttribute(T0 attr0, T1 attr1, T2 attr2, T3 attr3) { this.attr0 = attr0; this.attr1 = attr1; this.attr2 = attr2; this.attr3 = attr3; } public unsafe K Get(int index) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; return kk[0]; } case 1: fixed (T1* k = &attr1) { K* kk = (K*)k; return kk[0]; } case 2: fixed (T2* k = &attr2) { K* kk = (K*)k; return kk[0]; } case 3: fixed (T3* k = &attr3) { K* kk = (K*)k; return kk[0]; } default: throw new ArgumentOutOfRangeException(); } // Shorter idea but only C# 8.0: //fixed (void* v = &this) //{ // byte* b = (byte*)v; // b += Positions[index]; // return ((K*)b)[0]; //}; } public IMetaAttribute Set(int index, K value) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; kk[0] = value; return this; } case 1: fixed (T1* k = &attr1) { K* kk = (K*)k; kk[0] = value; return this; } case 2: fixed (T2* k = &attr2) { K* kk = (K*)k; kk[0] = value; return this; } case 3: fixed (T3* k = &attr3) { K* kk = (K*)k; kk[0] = value; return this; } default: throw new ArgumentOutOfRangeException(); } } } public unsafe struct MetaAttribute : IMetaAttribute where T0 : unmanaged where T1 : unmanaged where T2 : unmanaged where T3 : unmanaged where T4 : unmanaged { public T0 attr0; public T1 attr1; public T2 attr2; public T3 attr3; public T4 attr4; public MetaAttribute(T0 attr0, T1 attr1, T2 attr2, T3 attr3, T4 attr4) { this.attr0 = attr0; this.attr1 = attr1; this.attr2 = attr2; this.attr3 = attr3; this.attr4 = attr4; } public unsafe K Get(int index) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; return kk[0]; } case 1: fixed (T1* k = &attr1) { K* kk = (K*)k; return kk[0]; } case 2: fixed (T2* k = &attr2) { K* kk = (K*)k; return kk[0]; } case 3: fixed (T3* k = &attr3) { K* kk = (K*)k; return kk[0]; } case 4: fixed (T4* k = &attr4) { K* kk = (K*)k; return kk[0]; } default: throw new ArgumentOutOfRangeException(); } // Shorter idea but only C# 8.0: //fixed (void* v = &this) //{ // byte* b = (byte*)v; // b += Positions[index]; // return ((K*)b)[0]; //}; } public IMetaAttribute Set(int index, K value) where K : unmanaged { switch (index) { case 0: fixed (T0* k = &attr0) { K* kk = (K*)k; kk[0] = value; return this; } case 1: fixed (T1* k = &attr1) { K* kk = (K*)k; kk[0] = value; return this; } case 2: fixed (T2* k = &attr2) { K* kk = (K*)k; kk[0] = value; return this; } case 3: fixed (T3* k = &attr3) { K* kk = (K*)k; kk[0] = value; return this; } case 4: fixed (T4* k = &attr4) { K* kk = (K*)k; kk[0] = value; return this; } default: throw new ArgumentOutOfRangeException(); } } } }