Пример #1
0
        public void WriteDefinition(IFieldWriter writer)
        {
            writer.Write(m_IsCachable);
            int nestingDepth = GetNestingDepth();

            writer.Write(nestingDepth);
            writer.Write(m_DynamicTypeName);
            WriteDefinitionForThisLevel(writer);
        }
Пример #2
0
        public void Write(TextWriter writer, Type type)
        {
            WriteTypeKind(writer, type);
            writer.Write(" \"");

            _typeNameWriter.Write(writer, type);
            writer.Write("\" as ");
            _escapedTypeNameWriter.Write(writer, type);

            writer.WriteLine(" {");

            WriteMembers(
                writer,
                () => _queryType.GetFields(type),
                i => _fieldWriter.Write(writer, i));

            WriteMembers(
                writer,
                () => _queryType.GetProperties(type),
                i => _propertyWriter.Write(writer, i));

            WriteMembers(
                writer,
                () => _queryType.GetMethods(type),
                i => _methodWriter.Write(writer, i));

            WriteMembers(
                writer,
                () => _queryType.GetEvents(type),
                i => _eventWriter.Write(writer, i));

            writer.WriteLine("}");
        }
Пример #3
0
        /// <summary>
        /// Helper method to write out a single run (either repating or unique values)
        /// </summary>
        private void WriteRun(T[] array, IFieldWriter writer,
                              ref int runLength, ref int currentIndex, ref int peekIndex)
        {
            // This handles the edge case of the last run containing only one value
            if (currentIndex == array.Length - 1)
            {
                runLength = -1;
            }

            // Write the length of the run first
            writer.Write(runLength);

            // is this a repeating run?
            if (runLength > 0)
            {
                // for a repeating run, write the value once but advance the index by runLength
                WriteValue(writer, array[currentIndex]);
                currentIndex += runLength;
            }
            else
            {
                // for a unique run, write each value
                while (runLength < 0)
                {
                    WriteValue(writer, array[currentIndex++]);
                    runLength++;
                }
            }

            // Having written this run, get ready for the next one
            peekIndex = currentIndex + 1;
            runLength = 0;
        }
Пример #4
0
        /// <summary>
        /// Request the packet object write out all of its fields.
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="writer"></param>
        internal void WriteFields(IPacket packet, IFieldWriter writer)
        {
            if (packet is GenericPacket)
            {
                //TODO: Update generic packet handling
                //packet.WriteFields(writer);
            }
            else
            {
                //We need all of our base classes to write out before us
                if (m_BasePacket != null)
                {
                    m_BasePacket.WriteFields(packet, writer);
                }

                //and finally write out our information, if we have any.
                if (m_WriteMethod != null && m_Fields.Count > 0)
                {
                    //we need to create a serialized packet for this new level so the write method can store information
                    SerializedPacket serializedPacket = new SerializedPacket(this);
                    m_WriteMethod.Invoke(packet, new object[] { this, serializedPacket });

                    //and now write out the fields to serialization.
                    for (int curFieldIndex = 0; curFieldIndex < Fields.Count; curFieldIndex++)
                    {
                        FieldDefinition fieldDefinition = Fields[curFieldIndex];
                        writer.Write(serializedPacket.Values[curFieldIndex], fieldDefinition.FieldType);
                    }
                }
            }
        }
Пример #5
0
        public void Write(TextWriter writer, Type type, IQueryType queryType)
        {
            WriteTypeKind(writer, type);
            writer.Write(' ');
            _typeNameWriter.Write(writer, type);

            if (type.BaseType != null)
            {
                writer.Write(" : ");
                _typeNameWriter.Write(writer, type.BaseType);
            }

            var implementedInterfaces = queryType.GetInterfaces(type).ToArray();

            if (implementedInterfaces.Length > 0)
            {
                writer.Write(" implements ");
                writer.Write(string.Join(',', implementedInterfaces.Select(_typeNameConverter.ToString)));
            }

            writer.WriteLine(" {");

            WriteMembers("Fields",
                         writer,
                         () => queryType.GetFields(type),
                         i => _fieldWriter.Write(writer, i));

            WriteMembers("Properties",
                         writer,
                         () => queryType.GetProperties(type),
                         i => _propertyWriter.Write(writer, i));

            WriteMembers("Methods",
                         writer,
                         () => queryType.GetMethods(type),
                         i => _methodWriter.Write(writer, i));

            WriteMembers("Events",
                         writer,
                         () => queryType.GetEvents(type),
                         i => _eventWriter.Write(writer, i));

            writer.WriteLine("}");
        }
Пример #6
0
        private void WriteDefinitionForThisLevel(IFieldWriter writer)
        {
            if (m_BasePacket != null)
            {
                m_BasePacket.WriteDefinitionForThisLevel(writer);
            }

            writer.Write(m_TypeName);
            writer.Write(m_Version);
            writer.Write(m_Fields.Count);

            foreach (FieldDefinition fieldDefinition in m_Fields)
            {
                writer.Write(fieldDefinition.Name);
                writer.Write((int)fieldDefinition.FieldType);
            }

            // Writer out any associated sub-packets
            writer.Write(m_SubPackets.Count);
            for (int i = 0; i < m_SubPackets.Count; i++)
            {
                m_SubPackets[i].WriteDefinition(writer);
            }
        }
Пример #7
0
        /// <summary>
        /// Writes an array of type T to the stream.
        /// </summary>
        /// <param name="array">Data to be written</param>
        /// <param name="writer">Stream to write the data into</param>
        public void Write(T[] array, IFieldWriter writer)
        {
            writer.Write((UInt32)array.Length);

            int currentIndex = 0;
            int peekIndex    = currentIndex + 1;
            int runLength    = 0;

            // iterate across the array writing out a series of "runs" in which each
            // run is either a repetition of the same value or a sequence of unique values.
            while (currentIndex < array.Length)
            {
                // check for the end of the array
                if (peekIndex < array.Length)
                {
                    // is this the start of a new run?
                    if (runLength == 0)
                    {
                        // is this a run or repeated values?
                        if (AreEqual(array[peekIndex], array[peekIndex - 1]))
                        {
                            // since the first two values match, we know we have a run of at least 2 repeating values
                            runLength = 2;
                        }
                        else
                        {
                            // if the first two values differ, we have a run of at least 1 unique value
                            runLength = -1;
                        }
                        peekIndex += 1;
                    }
                    else if (runLength > 0)
                    {
                        // is the run of repeating values continuing?
                        if (AreEqual(array[peekIndex], array[peekIndex - 1]))
                        {
                            runLength += 1;
                            peekIndex += 1;
                        }
                        else
                        {
                            WriteRun(array, writer, ref runLength, ref currentIndex, ref peekIndex);
                        }
                    }
                    else // runLength < 0
                    {
                        // is the run of unique values continuing?
                        if (!AreEqual(array[peekIndex], array[peekIndex - 1]))
                        {
                            runLength -= 1; // we decrement because we're accumulating a negative length
                            peekIndex += 1;
                        }
                        else
                        {
                            // don't include the last value because it is part of the next (repeating) run
                            WriteRun(array, writer, ref runLength, ref currentIndex, ref peekIndex);
                        }
                    }
                }
                else
                {
                    WriteRun(array, writer, ref runLength, ref currentIndex, ref peekIndex);
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Write the data needed to serialize the state of the packet
        /// </summary>
        /// <param name="packet">Object to be serialized, must implement IPacket</param>
        public void Write(IPacket packet)
        {
            //Before we do anything - is this a cached packet that's already been written out?
            ICachedPacket cachedPacket = packet as ICachedPacket;

            if (cachedPacket != null)
            {
                //it is cacheable - is it in the cache?
                if (m_PacketCache.Contains(cachedPacket))
                {
                    //good to go, we're done.
                    return;
                }
            }

            //First, we need to find out if there are any packets this guy depends on.  If there are,
            //they have to be serialized out first.  They may have been - they could be cached.
            //to do this, we'll need to get the definition.
            PacketDefinition previewDefinition;
            int previewTypeIndex = m_CachedTypes.IndexOf(packet);

            if (previewTypeIndex < 0)
            {
                //we're going to get the definition, BUT we're not going to cache it yet.
                //This is because we recurse on our self if there are required packets, and if one of those
                //packets is our same type, IT has to write out the definition so that it's on the stream
                //before the packet itself.
                previewDefinition = PacketDefinition.CreatePacketDefinition(packet);
            }
            else
            {
                previewDefinition = m_CachedTypes[previewTypeIndex];
            }

            Dictionary <IPacket, IPacket> requiredPackets = previewDefinition.GetRequiredPackets(packet);

            foreach (IPacket requiredPacket in requiredPackets.Values)
            {
                Write(requiredPacket); //this will handle if it's a cached packet and shouldn't be written out.
            }

            //Begin our "transactional" phase
            try
            {
                // This routine is written to either write a complete packet, or to write nothing.
                // As we build up the packet, we will write to a MemoryStream.  Only after we've
                // built up the complete packet will we write it to the actual stream.
                m_Buffer.SetLength(0);
                m_Buffer.Position = 0;

                // The first time a packet type is written, we send along a packet definition
                PacketDefinition definition;
                int typeIndex = m_CachedTypes.IndexOf(packet);
                if (typeIndex < 0)
                {
                    // Record that we've seen this type so we don't bother sending the PacketDefinition again
                    definition = PacketDefinition.CreatePacketDefinition(packet);
                    typeIndex  = m_CachedTypes.Count;
                    m_CachedTypes.Add(definition);

                    // Each packet always starts with a packet type index.  And the first time a new
                    // index is used, it is followed by the packet definition.
                    m_BufferWriter.Write((UInt32)typeIndex);
                    definition.WriteDefinition(m_BufferWriter);
                }
                else
                {
                    // If this type has been written before, just send the type index
                    m_BufferWriter.Write((UInt32)typeIndex);
                    definition = m_CachedTypes[typeIndex];
                }

                // if it's cacheable then we need to add it to our packet cache before we write it out
                if (definition.IsCachable)
                {
                    // In the case of an ICachedPacket, we need to add it to the cache.
                    // we'd have already bailed if it was in there.
                    // Note: Use previous cast for efficiency, but we must recast here *if* packet gets reassigned above
                    // Currently it does not get reassigned, so cachedPacket which we cast packet into above is still valid.
                    m_PacketCache.AddOrGet(cachedPacket);
                }

                //Finally, and it really is a long journey, we ask the definition to write out
                //the individual fields for the packet
                definition.WriteFields(packet, m_BufferWriter);
            }
            catch (Exception ex)
            {
                GC.KeepAlive(ex);
                Rollback();
                throw;
            }

#if ADD_GUARD_BYTES
            m_Stream.Write(s_PreambleGuardPattern, 0, s_PreambleGuardPattern.Length);
#endif

            // Write the data to the stream preceded by the length of this packet
            // NOTE: The logic below is careful to ensure that the length and payload is written in one call
            //       This is necessary to ensure that the GZipStream writes the whole packet in edge cases
            //       of writing the very last packet as an application is exiting.

            var          payloadLength = (int)m_Buffer.Position; // get the actual length of the payload
            MemoryStream encodedLength = FieldWriter.WriteLength(payloadLength);
            var          lengthLength  = (int)encodedLength.Length;

            var packetBytes = new byte[lengthLength + payloadLength];

            encodedLength.Position = 0; // reset the position in preparation to read the data back
            encodedLength.Read(packetBytes, 0, lengthLength);

            m_Buffer.Position = 0; // reset the position in preparation to read the data back
            m_Buffer.Read(packetBytes, lengthLength, payloadLength);

            m_Stream.Write(packetBytes, 0, packetBytes.Length);

#if ADD_GUARD_BYTES
            m_Stream.Write(s_PostambleGuardPattern, 0, s_PostambleGuardPattern.Length);
#endif

            Commit();
        }