Example #1
0
        private static ArrayRange <RenderTreeFrame> ReadReferenceFrames(ReadOnlySpan <byte> data, string[] strings)
        {
            var result = new RenderTreeFrame[data.Length / ReferenceFrameSize];

            for (var i = 0; i < data.Length; i += ReferenceFrameSize)
            {
                var frameData = data.Slice(i, ReferenceFrameSize);

                var type = (RenderTreeFrameType)BitConverter.ToInt32(frameData.Slice(0, 4));

                // We want each frame to take up the same number of bytes, so that the
                // recipient can index into the array directly instead of having to
                // walk through it.
                // Since we can fit every frame type into 16 bytes, use that as the
                // common size. For smaller frames, we add padding to expand it to
                // 16 bytes.
                switch (type)
                {
                case RenderTreeFrameType.Attribute:
                    var attributeName           = ReadString(frameData.Slice(4, 4), strings);
                    var attributeValue          = ReadString(frameData.Slice(8, 4), strings);
                    var attributeEventHandlerId = BitConverter.ToUInt64(frameData.Slice(12, 8));
                    result[i / ReferenceFrameSize] = RenderTreeFrame.Attribute(0, attributeName, attributeValue).WithAttributeEventHandlerId(attributeEventHandlerId);
                    break;

                case RenderTreeFrameType.Component:
                    var componentSubtreeLength = BitConverter.ToInt32(frameData.Slice(4, 4));
                    var componentId            = BitConverter.ToInt32(frameData.Slice(8, 4)); // Nowhere to put this without creating a ComponentState
                    result[i / ReferenceFrameSize] = RenderTreeFrame.ChildComponent(0, componentType: null)
                                                     .WithComponentSubtreeLength(componentSubtreeLength)
                                                     .WithComponent(new ComponentState(Renderer, componentId, new FakeComponent(), null));
                    break;

                case RenderTreeFrameType.ComponentReferenceCapture:
                    // Client doesn't process these, skip.
                    result[i / ReferenceFrameSize] = RenderTreeFrame.ComponentReferenceCapture(0, null, 0);
                    break;

                case RenderTreeFrameType.Element:
                    var elementSubtreeLength = BitConverter.ToInt32(frameData.Slice(4, 4));
                    var elementName          = ReadString(frameData.Slice(8, 4), strings);
                    result[i / ReferenceFrameSize] = RenderTreeFrame.Element(0, elementName).WithElementSubtreeLength(elementSubtreeLength);
                    break;

                case RenderTreeFrameType.ElementReferenceCapture:
                    var referenceCaptureId = ReadString(frameData.Slice(4, 4), strings);
                    result[i / ReferenceFrameSize] = RenderTreeFrame.ElementReferenceCapture(0, null)
                                                     .WithElementReferenceCaptureId(referenceCaptureId);
                    break;

                case RenderTreeFrameType.Region:
                    var regionSubtreeLength = BitConverter.ToInt32(frameData.Slice(4, 4));
                    result[i / ReferenceFrameSize] = RenderTreeFrame.Region(0).WithRegionSubtreeLength(regionSubtreeLength);
                    break;

                case RenderTreeFrameType.Text:
                    var text = ReadString(frameData.Slice(4, 4), strings);
                    result[i / ReferenceFrameSize] = RenderTreeFrame.Text(0, text);
                    break;

                case RenderTreeFrameType.Markup:
                    var markup = ReadString(frameData.Slice(4, 4), strings);
                    result[i / ReferenceFrameSize] = RenderTreeFrame.Markup(0, markup);
                    break;

                default:
                    throw new ArgumentException($"Unsupported frame type: {type}");
                }
            }

            return(new ArrayRange <RenderTreeFrame>(result, result.Length));
        }