コード例 #1
0
            // writes a variable length 29-bit signed integer. sign does not matter, may take an unsigned int.
            void UnmarkedWriteInt29(int value)
            {
                Kon.Assert(value >= -268435456 && value <= 268435455, "value isn't in the range of encodable 29-bit numbers");

                // sign contraction - the high order bit of the resulting value must match every bit removed from the number
                // clear 3 bits
                value = value & 0x1fffffff;

                if (value < 0x80)
                {
                    b.WriteByte((byte)value);
                }
                else if (value < 0x4000)
                {
                    b.WriteByte((byte)(value >> 7 & 0x7f | 0x80));
                    b.WriteByte((byte)(value & 0x7f));
                }
                else if (value < 0x200000)
                {
                    b.WriteByte((byte)(value >> 14 & 0x7f | 0x80));
                    b.WriteByte((byte)(value >> 7 & 0x7f | 0x80));
                    b.WriteByte((byte)(value & 0x7f));
                }
                else
                {
                    b.WriteByte((byte)(value >> 22 & 0x7f | 0x80));
                    b.WriteByte((byte)(value >> 15 & 0x7f | 0x80));
                    b.WriteByte((byte)(value >> 8 & 0x7f | 0x80));
                    b.WriteByte((byte)(value & 0xff));
                }
            }
コード例 #2
0
        public static void Polimorfizm(int index)
        {
            Ssak ssak;

            switch (index)
            {
            case 1:
                ssak = new Kon();
                break;

            case 2:
                ssak = new Zebra();
                break;

            case 3:
                ssak = new Delfin();
                break;

            default:
                ssak = new Ssak();
                break;
            }

            ssak.Mowa();

            // Na podstawie podanego parametru mogę utworzyć różny obiek i za pomocą jednej instrukcji wykonać metodę zaimplementowaną w sposób zależny od klasy.
        }
コード例 #3
0
        public static void Init()
        {
            Ssak mojSsak = new Ssak();
            Kon  mojKon  = new Kon();

            mojKon.ZaluzSiodlo();
            mojSsak = mojKon;
            mojSsak.ZaluzSiodlo(); // błąd. Odwołujac się do obiektu klasy Kon za pomocą zmiennej typu 'Ssak' możemy korzystać tylko z metod i właściwości zdefiniowanych w klasie 'Ssak'
                                   // Metoda ZaluzSiodlo() (ang. put saddle) jest tylko w klasie Kon.

            Ssak jakisSsak = new Ssak();
            // Kon jakisKon = jakisSsak;  // błąd. Nie można przypisać obiektu klasy 'Ssak' to zmiennej typu 'Kon'. Klasa 'Kon' "rozszerza" klase 'Ssak' i zawiera wiecej pól i metod, dlatego jest to niemożliwe.

            // Możliwe jest przypisanie pod warunkiem, że obiekt klasy 'Ssak' tak naprawde jest Koniem. Można to sprawdzić za pomocą operatorów 'as', 'is' lub rzutowania przykład poniżej.
            Kon  konik = new Kon();
            Ssak ssak  = konik;
            Kon  konPonownie;

            if (ssak is Kon)
            {
                konPonownie = (Kon)ssak;
            }

            Delfin delfin = new Delfin();

            ssak = delfin;

            konPonownie = ssak as Kon; // Oprator as zwróci 'null', gdyż obiekt 'ssak' jest rownież obiektem klasy 'Delfin' a nie 'Kon'.
        }
コード例 #4
0
        public static void Przesłanianie() // Nazewnictwo: nadpisanie/przesłanianie metody
        {
            /* Metoda która z założenia służy do tego, aby została przeszłonięta przez inna implementacje nazywamy metodą 'wirtualną'.
             * Więcej o metodzie wirtualnej i override w klasie 'Ssak' i 'Kon'.
             * Różnica pomiedzy 'Przesłonięciem'(ang. overriding) a 'Ukrywaniem'
             * Przesłonięcie metody polega na tym aby metoda wykonywała te same zadanie w sposób zależny od danej klasy.
             * Ukrycie metody - metody mogą wykonywać dwa całkowicie różne zadania. Ukrycie metody jest często błędem.
             */

            Ssak   ssak  = new Ssak();
            Kon    kon   = new Kon();
            Zebra  zebra = new Zebra();
            Delfin defin = new Delfin();


            /* Metoda wirtalna a 'polimorfizm'
             * Przy pomocy metod wirtualnych można wywoływać różne wersje tej samej metody w zależności od faktycznego typu obiektu przekazanego do zmiennej.
             * Typ obiektu może być tworzony dynamicznie, w trakcie działania programu.
             */
            // W klasie Ssak metoda Mowa() jest virtualna. Klasa Kon ją nadpisuje (override).
            ssak = kon;
            ssak.Mowa(); // Wykona się metoda z klasy Kon.

            ssak = zebra;
            ssak.Mowa(); // Wykona się metoda z klasy Zebra.

            // defin nie implementuje metody Mowa()
            ssak = defin;
            ssak.Mowa(); // Wykona się metoda z klasy Ssak.

            /*Note: Gdyby metoda Mowa() była ukryta a nie nadpisana to wykonałaby się metoda z klasy Ssak.
             * Jednak tak nie jest i na tym właśnie polaga polimorfizm (wiele form).
             */
        }
コード例 #5
0
            // this method must only be called once
            public async Task RunAsync(int chunkLength)
            {
                if (chunkLength != 0)
                {
                    QueueWrite(new ChunkLength(chunkLength), chunkStreamId: 2, external: false);
                    this.chunkLength = chunkLength;
                }

                while (!token.IsCancellationRequested)
                {
                    try
                    {
                        await WriteOnceAsync();
                    }
                    catch (TaskCanceledException)
                    {
                        return;
                    }
                    catch (Exception e)
                    {
                        Kon.DebugException("rtmpclient::writer encountered an error", e);

                        owner.InternalCloseConnection("writer-exception", e);
                        return;
                    }
                }
            }
コード例 #6
0
        public static Socket FastSocket(Socket socket)
        {
            CheckDebug.NotNull(socket);

            socket.NoDelay = true;

            if (IsWindows)
            {
                unchecked
                {
                    try
                    {
                        // defined in `mstcpip.h`
                        const int SIO_LOOPBACK_FAST_PATH = (int)0x98000010;
                        socket.IOControl(SIO_LOOPBACK_FAST_PATH, optionInValue: Yes, optionOutValue: null);
                    }
                    catch (Exception e)
                    {
                        Kon.DebugException(e);
                    }
                }
            }

            return(socket);
        }
コード例 #7
0
ファイル: Doska.cs プロジェクト: 70rustsk/repos
        // Перемещаем фигуру из одной ячейки в другую, после того как эта функция будет вызвана
        public void Move(Yacheika from, Yacheika to, PromoteOptions promoteOption)
        {
            if (to.Piece != null)
            {
                pieces.Remove(to.Piece);
            }
            to.Piece   = from.Piece;
            from.Piece = null;
            if (to == EnPassant && to.Piece is Peshka)
            {
                pieces.Remove(EnPassantCapture.Piece);
                EnPassantCapture.Piece = null;
            }
            if (to.Piece is Korol && to.X - from.X == 2)                        // Рокировка вправо
            {
                Move(GetCell(7, to.Y), GetCell(to.X - 1, to.Y), promoteOption); // Перемещаем ладью
            }
            if (to.Piece is Korol && to.X - from.X == -2)                       // Рокировка влево
            {
                Move(GetCell(0, to.Y), GetCell(to.X + 1, to.Y), promoteOption); // Перемещаем ладью
            }
            if (to.Piece is Peshka && to.Y == (to.Piece.Color == PlayerColor.White ? 7 : 0))
            {
                Piece promoted = null;
                switch (promoteOption)
                {
                case PromoteOptions.Queen:
                    promoted = new Dama(to.Piece);
                    break;

                case PromoteOptions.Rook:
                    promoted = new Ladiya(to.Piece);
                    break;

                case PromoteOptions.Bishop:
                    promoted = new Slon(to.Piece);
                    break;

                case PromoteOptions.Knight:
                    promoted = new Kon(to.Piece);
                    break;
                }
                //Обновляем список
                pieces.Remove(to.Piece);
                to.Piece = promoted;
                promoted.OnPlace(to);
                pieces.Add(promoted);
            }
            // Пересчитаем возможные ходы
            to.Piece.OnMove(to);
            to.Piece.Recalculate();
            EnPassant        = null;
            EnPassantCapture = null;
            if (to.Piece is Peshka && Math.Abs(to.Y - from.Y) == 2)
            {
                EnPassant        = GetCell(to.X, (from.Y > to.Y) ? from.Y - 1 : from.Y + 1);
                EnPassantCapture = to;
            }
        }
コード例 #8
0
            public static void WriteTo(AmfWriter writer, Snapshot previous, Snapshot next, int chunkLength, Space <byte> message)
            {
                Kon.Assert(
                    !previous.Ready || previous.ChunkStreamId == next.ChunkStreamId,
                    "previous and next describe two different chunk streams");

                Kon.Assert(
                    next.MessageLength == message.Length,
                    "mismatch between reported message length and actual message length");

                // we don't write zero-length packets, and as state for `next` and `previous` won't match what our peer
                // sees if we pass a zero-length message here. zero-length sends should be filtered out at a higher level.
                Kon.Assert(
                    next.MessageLength != 0,
                    "message length cannot be zero");


                var header = GetInitialHeaderType();

                for (var i = 0; i < next.MessageLength; i += chunkLength)
                {
                    if (i == 0)
                    {
                        BasicHeader.WriteTo(writer, (byte)header, next.ChunkStreamId);
                        MessageHeader.WriteTo(writer, header, next);
                    }
                    else
                    {
                        BasicHeader.WriteTo(writer, (byte)MessageHeader.Type.Type3, next.ChunkStreamId);
                    }

                    var count = Math.Min(chunkLength, next.MessageLength - i);
                    var slice = message.Slice(i, count);

                    writer.WriteBytes(slice);
                }


                MessageHeader.Type GetInitialHeaderType()
                {
                    if (!previous.Ready || next.MessageStreamId != previous.MessageStreamId)
                    {
                        return(MessageHeader.Type.Type0);
                    }

                    if (next.MessageLength != previous.MessageLength || next.ContentType != previous.ContentType)
                    {
                        return(MessageHeader.Type.Type1);
                    }

                    if (next.Timestamp != previous.Timestamp)
                    {
                        return(MessageHeader.Type.Type2);
                    }

                    return(MessageHeader.Type.Type3);
                }
            }
コード例 #9
0
        // Ważną zaletą Dziedziczenia jest to, że do tej metody mogę przekazać każdy obiekt klasy dziedziczącej po klase bazowej.
        public static void Konwersja(Ssak ssak)
        {
            Kon mojKon = ssak as Kon; // Wiecej na temat 'as' w rozdział 8 Wartości i Referecje - SaveCasting

            if (mojKon != null)
            {
                mojKon.ZaluzSiodlo();
            }
        }
コード例 #10
0
            // helpers
            void Require(int count)
            {
                Kon.Assert(count <= temporary.Length);

                if (reader.ReadUnchecked(temporary, 0, count) != count)
                {
                    throw new EndOfStreamException();
                }
            }
コード例 #11
0
ファイル: Check.cs プロジェクト: sbyt3/IcyWind-Official
        static void DebugBreak()
        {
#if DEBUG
            var traceLines = Environment.StackTrace.Split('\n').Select(x => $"    {x}");
            var trace      = string.Join("\n", traceLines);

            Kon.Critical($"invalid null passed at\n{trace}");
            Debugger.Break();
#endif
        }
コード例 #12
0
        public void ReadLoop()
        {
            try
            {
                while (Continue)
                {
                    var header = ReadHeader();
                    rtmpHeaders[header.StreamId] = header;

                    RtmpPacket packet;
                    if (!rtmpPackets.TryGetValue(header.StreamId, out packet) || packet == null)
                    {
                        packet = new RtmpPacket(header);
                        rtmpPackets[header.StreamId] = packet;
                    }

                    var remainingMessageLength = packet.Length + (header.Timestamp >= 0xFFFFFF ? 4 : 0) - packet.CurrentLength;
                    var bytesToRead            = Math.Min(remainingMessageLength, readChunkSize);
                    var bytes = reader.ReadBytes(bytesToRead);
                    packet.AddBytes(bytes);

                    if (packet.IsComplete)
                    {
                        rtmpPackets.Remove(header.StreamId);

                        var @event = ParsePacket(packet);
                        OnEventReceived(new EventReceivedEventArgs(@event));

                        // process some kinds of packets
                        var chunkSizeMessage = @event as ChunkSize;
                        if (chunkSizeMessage != null)
                        {
                            readChunkSize = chunkSizeMessage.Size;
                        }

                        var abortMessage = @event as Abort;
                        if (abortMessage != null)
                        {
                            rtmpPackets.Remove(abortMessage.StreamId);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
#if DEBUG && WITH_KONSEKI
                Kon.DebugException($"exception occurred", ex);
#endif

                OnDisconnected(new ExceptionalEventArgs("rtmp-packet-reader", ex));
            }
        }
コード例 #13
0
        static void Welcome()
        {
            // 我が名は仙狐。
            // The project has been renamed to Senko, after the helpful fox in the anime "Sewayaki Kitsune no Senko-san"
            // Senko is also a backronym for "SENd KOmmand".

            string title = Color.InsertTag("PROJECT:SENKO | Remote Control", ConsoleColor.Cyan);

            System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
            FileVersionInfo            fvi      = FileVersionInfo.GetVersionInfo(assembly.Location);
            string version = "Version: " + fvi.ProductVersion;

            version = Color.InsertTag(version.Join("@", 43 - version.Length, "#"), ConsoleColor.White);

            string github = Color.InsertTag(@"https://github.com/TsurugiDanzen/Senko", ConsoleColor.White);

            var ascii = new string[]
            {
                "@26#,.",
                "@17#.*&&4@# .#@@@%*",
                "@16##@@%,.&@&@@@//@%,",
                "@13#.%@@(,  ,@@@&/  ,@#,",
                "@11#,#@%/@6#,*.@4#.&@@(.@15#",
                "@10#*@@#@17#*#@@@/.",
                "@9#,@&(@21#,/&@@%",
                "@8#,@%@17#,/%@@@&%/.",
                "@7#*%@,@15#*@@@%*, ,/%&&8@}%#/.",
                "@7#%@#@15#/&@,.*%&@@@%(*,...,,*#&@@%(",
                "@6#,@@,@15#.(&4@%#,@15#*@@%",
                "@5#,#@%@42#*@%,",
                "@5#,%@%@42#,@%,",
                "@6#,,.   ./%&&15@&%(,.@13#.%@@.  /*",
                "@9#,%@@@%(,.@10#..*#%&@@@&%(,,,.,,*#&@@%.  ,@@,",
                "@6#.#&@&*,@23#,(#&&7@&%*@6#&@(",
                "@4#(@@%/@47#%@#",
                "  *%@#*@5#{0}@14#&@(",
                " *@@/@7#{1}*@@,",
                ",@@&%#(,.   {2}@4#.@&(",
                ",##%%&@@@#,@42#/&@*",
                Color.InsertTag(new string('#', Kon.MaxLength(PrefixType.Normal)), ConsoleColor.DarkGray, false),
                Environment.NewLine
            }.Join(Environment.NewLine);

            Kon.WriteLine(ascii.Decompress(), LongTextFormatting.Disabled, NewLineType.Both, ConsoleColor.Gray, PrefixType.Normal, title, version.Decompress(), github);
            Kon.WriteLine();
            Kon.Color.Reset();
        }
コード例 #14
0
        static void Main(string[] args)
        {
            Console.WriteLine("IPhone interface:");
            Phone small = new Phone(new Small());
            Phone big   = new Phone(new Big());

            small.Start();
            big.Start();
            Console.WriteLine();
            Console.WriteLine("Demonstration of IComp interface:");
            Kon ch = new Kon(new Cheap());
            Kon ex = new Kon(new Exp());

            ch.Start();
            ex.Start();
            Console.ReadKey();
        }
コード例 #15
0
        public static void Ukrywanie() // Nazewnictwo: maskowanie/ukrycie metody. Chodzi o to samo.
        {
            /* Klasy Kon i Ssak posiadają metody o takiej samej sygnaturze - public void PobierzImie().
             * Kon ukrywa metode Ssak.PobierzImie() i tworzy własną - public new void PobierzImie().
             * Gdy jakaś klasa dziedziczyć bedzie po klasie 'Kon' to odziedziczy tą metodę po klasie 'Kon' a nie 'Ssak'. Ponieważ ta metoda została ukryta.
             */

            Kon   kon     = new Kon("Konik");
            Ssak  ssakKon = new Kon("Konik Roman");
            Zebra zebra   = new Zebra("Zebra Irena");

            kon.PobierzImie();     // Wynik na konsoli 'Lubie biegac!'
            ssakKon.PobierzImie(); //Wynik na konsoli 'Konik Roman'
            zebra.PobierzImie();   // Wynik na konsoli 'Lubie biegac!'

            // Note: Na sygnaturę metody składa się: nazwa metody oraz ilość i typ parametrów. Typ zwracanej wartośćci nie ma znaczenia.
        }
コード例 #16
0
            // this method must only be called once
            public async Task RunAsync()
            {
                while (!token.IsCancellationRequested)
                {
                    try
                    {
                        await ReadOnceAsync();
                    }
                    catch (TaskCanceledException)
                    {
                        return;
                    }
                    catch (Exception e)
                    {
                        Kon.DebugException("rtmpclient::reader encountered an error", e);

                        owner.InternalCloseConnection("reader-exception", e);
                        return;
                    }
                }
            }
コード例 #17
0
        static void Main(string[] args)
        {
            Welcome();

            var dev = new SonyDevice("hub");

            dev.Alias.Add("xbox", "action");

            Kon.WriteLine("Device Model: " + dev.Info.Model);
            Kon.WriteLine("HDMI IRCode: " + dev.Command.Code["Hdmi1"]);
            Kon.WriteLine("Netflix: " + dev.Apps.List["Netflix"]);
            Kon.WriteLine("<test><green><tags>abcdefg\n<testagain>", WriteParameters.MinimalProcessing);
            Kon.WriteLine("Write this with and Indent prefix. Let's see if it works as I expect the program to work.", PrefixType.Indent);
            Kon.WriteLine("Test", WriteParameters.OffTheRecord);
            Kon.WriteLine("The quick brown fox jumps over the lazy dog.\nThe quick brown fox jumps over the lazy dog.");
            Kon.WriteLine("The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. ");
            Kon.WriteLine("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789<green>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz<magenta>ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbb");
            Kon.WriteLine("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS<green>TUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstu vwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", LongTextFormatting.Truncate);
            Kon.WriteLine("test...");
            Kon.WriteLine(@"https://www.bing.com/search?q=remove+string+from+index+c%23&form=EDGEAR&qs=PF&cvid=d00610ea914c4bc9b5c105a59bd118a6&cc=US&setlang=en-US&plvar=0");

            var colorsplitter = new Color.Splitter(SplitMode.Word, Palette.Rainbow);

            Kon.WriteLine("The quick brown fox jumps over the lazy dog in \"rainbow\" colors", colorsplitter);

            Encapsulator tag = new Encapsulator("<red>", "</>");

            Kon.WriteLine("This should be red.".Encapsulate(tag).Encapsulate("([{<"));

            //WriteLog();

            while (true)
            {
                //string read = Kon.ReadLine();

                //ParseCommand(read);
            }
        }
コード例 #18
0
        public void ReadLoop()
        {
            try
            {
                while (Continue)
                {
                    ReadOnce();
                }
            }
            catch (Exception ex) when(ex is EndOfStreamException || ex is IOException)
            {
                OnDisconnected(new ExceptionalEventArgs("rtmp-packet-reader", ex));
                return;
            }
            catch (Exception)
            {
#if DEBUG && WITH_KONSEKI
                Kon.DebugException($"exception occurred", ex);
#endif

                throw;
            }
        }
コード例 #19
0
            bool ReadSingleFrame(AmfReader reader)
            {
                if (!ChunkStream.ReadFrom1(reader, out var streamId, out var opaque))
                {
                    return(false);
                }

                if (!streams.TryGetValue(streamId, out var previous))
                {
                    previous = new ChunkStream.Snapshot()
                    {
                        ChunkStreamId = streamId
                    }
                }
                ;

                if (!ChunkStream.ReadFrom2(reader, previous, opaque, out var next))
                {
                    return(false);
                }

                streams[streamId] = next;
                context.RequestReadAllocation(next.MessageLength);

                var key     = (next.ChunkStreamId, next.MessageStreamId);
                var builder = messages.TryGetValue(key, out var packet) ? packet : messages[key] = new Builder(next.MessageLength);
                var length  = Math.Min(chunkLength, builder.Remaining);

                if (!reader.HasLength(length))
                {
                    return(false);
                }

                builder.AddData(
                    reader.ReadSpan(length));

                if (builder.Current == builder.Length)
                {
                    messages.Remove(key);

                    using (builder)
                    {
                        var dereader = __readSingleFrameReader;
                        dereader.Rebind(builder.Span);

                        var message = Deserialize(next.ContentType, dereader);
                        DispatchMessage(message);
                    }
                }

                return(true);
            }

            void DispatchMessage(RtmpMessage message)
            {
                switch (message)
                {
                case ChunkLength chunk:
                    Kon.Trace("received: chunk-length", new { length = chunk.Length });

                    if (chunk.Length < 0)
                    {
                        throw new ArgumentException("invalid chunk length");
                    }

                    context.RequestReadAllocation(chunk.Length);
                    chunkLength = chunk.Length;
                    break;

                case WindowAcknowledgementSize acknowledgement:
                    if (acknowledgement.Count < 0)
                    {
                        throw new ArgumentException("invalid acknowledgement window length");
                    }

                    acknowledgementLength = acknowledgement.Count;
                    break;

                case Abort abort:
                    Kon.Trace("received: abort", new { chunk = abort.ChunkStreamId });

                    // delete the chunk stream
                    streams.Remove(abort.ChunkStreamId);

                    // then, delete all message streams associated with that chunk stream
                    foreach (var(key, builder) in messages.FilterArray(x => x.Key.chunkStreamId == abort.ChunkStreamId))
                    {
                        messages.Remove(key);
                        builder.Dispose();
                    }

                    break;

                default:
                    owner.InternalReceiveEvent(message);
                    break;
                }
            }

            // todo: refactor
            RtmpMessage Deserialize(PacketContentType contentType, AmfReader r)
            {
                // (this comment must be kept in sync at rtmpclient.reader.cs and rtmpclient.writer.cs)
                //
                // unsupported type summary:
                //
                // - aggregate:      we have never encountered this packet in the wild
                // - shared objects: we have not found a use case for this
                // - data commands:  we have not found a use case for this, though it should be extremely easy to
                //                       support. it's just a one-way equivalent of command (invoke). that is, we don't
                //                       generate an invoke id for it, and it does not contain headers. other than that,
                //                       they're identical. we can use existing logic and add if statements to surround
                //                       writing the invokeid + headers if needed.

                switch (contentType)
                {
                case PacketContentType.SetChunkSize:
                    return(new ChunkLength(
                               length: r.ReadInt32()));

                case PacketContentType.AbortMessage:
                    return(new Abort(
                               chunkStreamId: r.ReadInt32()));

                case PacketContentType.Acknowledgement:
                    return(new Acknowledgement(
                               read: r.ReadUInt32()));

                case PacketContentType.UserControlMessage:
                    var type   = r.ReadUInt16();
                    var values = EnumerableEx.Range(r.Remaining / 4, r.ReadUInt32);

                    return(new UserControlMessage(
                               type:   (UserControlMessage.Type)type,
                               values: values));

                case PacketContentType.WindowAcknowledgementSize:
                    return(new WindowAcknowledgementSize(
                               count: r.ReadInt32()));

                case PacketContentType.SetPeerBandwith:
                    return(new PeerBandwidth(
                               acknowledgementWindowSize: r.ReadInt32(),
                               type:                 r.ReadByte()));

                case PacketContentType.Audio:
                    return(new AudioData(
                               r.ReadBytes(r.Remaining)));

                case PacketContentType.Video:
                    return(new VideoData(
                               r.ReadBytes(r.Remaining)));

                case PacketContentType.DataAmf0:
                    throw NotSupportedException("data-amf0");

                case PacketContentType.SharedObjectAmf0:
                    throw NotSupportedException("sharedobject-amf0");

                case PacketContentType.CommandAmf0:
                    return(ReadCommand(ObjectEncoding.Amf0, contentType, r));

                case PacketContentType.DataAmf3:
                    throw NotSupportedException("data-amf3");

                case PacketContentType.SharedObjectAmf3:
                    throw NotSupportedException("sharedobject-amf0");

                case PacketContentType.CommandAmf3:
                    var encoding = (ObjectEncoding)r.ReadByte();
                    return(ReadCommand(encoding, contentType, r));

                case PacketContentType.Aggregate:
                    throw NotSupportedException("aggregate");

                default:
                    throw NotSupportedException($"unknown ({contentType})");
                }
            }