/// <summary> /// Compose a structure into an array of bytes /// </summary> /// <param name="value">Structure to compose</param> /// <param name="connection">DistributedConnection is required in case an item in the structure is at the other end</param> /// <param name="includeKeys">Whether to include the structure keys</param> /// <param name="includeTypes">Whether to include each item DataType</param> /// <param name="prependLength">If true, prepend the length as UInt32 at the beginning of the returned bytes array</param> /// <returns>Array of bytes in the network byte order</returns> public static byte[] ComposeStructure(Structure value, DistributedConnection connection, bool includeKeys = true, bool includeTypes = true, bool prependLength = false) { var rt = new BinaryList(); if (includeKeys) { foreach (var i in value) { var key = DC.ToBytes(i.Key); rt.Append((byte)key.Length, key, Compose(i.Value, connection)); } } else { foreach (var i in value) { rt.Append(Compose(i.Value, connection, includeTypes)); } } if (prependLength) { rt.Insert(0, rt.Length); } return(rt.ToArray()); }
/// <summary> /// Compose resource history /// </summary> /// <param name="history">History</param> /// <param name="connection">DistributedConnection is required to fetch resources.</param> /// <returns></returns> public static byte[] ComposeHistory(KeyList <PropertyTemplate, PropertyValue[]> history, DistributedConnection connection, bool prependLength = false) { var rt = new BinaryList(); for (var i = 0; i < history.Count; i++) { rt.Append((byte)history.Keys.ElementAt(i).Index, ComposePropertyValueArray(history.Values.ElementAt(i), connection, true)); } if (prependLength) { rt.Insert(0, (uint)rt.Length); } return(rt.ToArray()); }
/// <summary> /// Compose an array of resources /// </summary> /// <param name="resources">Array of resources.</param> /// <param name="connection">DistributedConnection is required to check locality.</param> /// <param name="prependLength">If True, prepend the length of the output at the beginning.</param> /// <returns>Array of bytes in the network byte order.</returns> public static byte[] ComposeResourceArray(IResource[] resources, DistributedConnection connection, bool prependLength = false) { if (resources == null || resources?.Length == 0) { return prependLength ? new byte[] { 0, 0, 0, 0 } } : new byte[0]; var rt = new BinaryList(); var comparsion = Compare(null, resources[0], connection); rt.Append((byte)comparsion); if (comparsion == ResourceComparisonResult.Local) { rt.Append((resources[0] as DistributedResource).Id); } else if (comparsion == ResourceComparisonResult.Distributed) { rt.Append(resources[0].Instance.Id); } for (var i = 1; i < resources.Length; i++) { comparsion = Compare(resources[i - 1], resources[i], connection); rt.Append((byte)comparsion); if (comparsion == ResourceComparisonResult.Local) { rt.Append((resources[i] as DistributedResource).Id); } else if (comparsion == ResourceComparisonResult.Distributed) { rt.Append(resources[i].Instance.Id); } } if (prependLength) { rt.Insert(0, rt.Length); } return(rt.ToArray()); }
/// <summary> /// Compose an array of structures into an array of bytes /// </summary> /// <param name="structures">Array of Structure to compose</param> /// <param name="connection">DistributedConnection is required in case a structure in the array holds items at the other end</param> /// <param name="prependLength">If true, prepend the length as UInt32 at the beginning of the returned bytes array</param> /// <returns>Array of bytes in the network byte order</returns> public static byte[] ComposeStructureArray(Structure[] structures, DistributedConnection connection, bool prependLength = false) { if (structures == null || structures?.Length == 0) { return prependLength ? new byte[] { 0, 0, 0, 0 } } : new byte[0]; var rt = new BinaryList(); var comparsion = StructureComparisonResult.Structure; rt.Append((byte)comparsion); rt.Append(ComposeStructure(structures[0], connection, true, true, true)); for (var i = 1; i < structures.Length; i++) { comparsion = Compare(structures[i - 1], structures[i], connection); rt.Append((byte)comparsion); if (comparsion == StructureComparisonResult.Structure) { rt.Append(ComposeStructure(structures[i], connection, true, true, true)); } else if (comparsion == StructureComparisonResult.StructureSameKeys) { rt.Append(ComposeStructure(structures[i], connection, false, true, true)); } else if (comparsion == StructureComparisonResult.StructureSameTypes) { rt.Append(ComposeStructure(structures[i], connection, false, false, true)); } } if (prependLength) { rt.Insert(0, rt.Length); } return(rt.ToArray()); }
/// <summary> /// Compose a variable /// </summary> /// <param name="value">Value to compose.</param> /// <param name="connection">DistributedConnection is required to check locality.</param> /// <param name="prependType">If True, prepend the DataType at the beginning of the output.</param> /// <returns>Array of bytes in the network byte order.</returns> public static byte[] Compose(object value, DistributedConnection connection, bool prependType = true) { if (value is Func <DistributedConnection, object> ) { value = (value as Func <DistributedConnection, object>)(connection); } else if (value is DistributedPropertyContext) { value = (value as DistributedPropertyContext).Method(connection); } var type = GetDataType(value, connection); var rt = new BinaryList(); switch (type) { case DataType.Void: // nothing to do; break; case DataType.String: var st = DC.ToBytes((string)value); rt.Append(st.Length, st); break; case DataType.Resource: rt.Append((value as DistributedResource).Id); break; case DataType.DistributedResource: //rt.Append((value as IResource).Instance.Template.ClassId, (value as IResource).Instance.Id); rt.Append((value as IResource).Instance.Id); break; case DataType.Structure: rt.Append(ComposeStructure((Structure)value, connection, true, true, true)); break; case DataType.VarArray: rt.Append(ComposeVarArray((object[])value, connection, true)); break; case DataType.ResourceArray: if (value is IResource[]) { rt.Append(ComposeResourceArray((IResource[])value, connection, true)); } else { rt.Append(ComposeResourceArray((IResource[])DC.CastConvert(value, typeof(IResource[])), connection, true)); } break; case DataType.StructureArray: rt.Append(ComposeStructureArray((Structure[])value, connection, true)); break; default: rt.Append(value); if (type.IsArray()) { rt.Insert(0, rt.Length); } break; } if (prependType) { rt.Insert(0, (byte)type); } return(rt.ToArray()); }