Ejemplo n.º 1
0
        /// <summary>
        /// Deserializes the given frame given a known width and height.
        /// </summary>
        /// <param name="serializedFrame">the frame data</param>
        /// <param name="width">the known width of the frame</param>
        /// <param name="height">the known height of the frame</param>
        /// <returns>a deserialized frame that's either a raw frame or a diff frame, depending on what was in the serialized string</returns>
        public ConsoleBitmapFrame DeserializeFrame(string serializedFrame, int width, int height)
        {
            var tokens = tokenizer.Tokenize(serializedFrame);
            var reader = new TokenReader<Token>(tokens);

            reader.Expect("[");
            var timestampToken = reader.Advance();
            var timestamp = new TimeSpan(long.Parse(timestampToken.Value));
            reader.Expect("]");

            reader.Expect("[");
            reader.Advance();
            var isDiff = reader.Current.Value == "Diff";
            reader.Expect("]");

            if (isDiff)
            {
                var diffFrame = new ConsoleBitmapDiffFrame()
                {
                    Timestamp = timestamp,
                    Diffs = new System.Collections.Generic.List<ConsoleBitmapPixelDiff>()
                };

                var lastBackground = ConsoleString.DefaultBackgroundColor;
                var lastForeground = ConsoleString.DefaultForegroundColor;
                while (reader.CanAdvance(skipWhitespace: true))
                {
                    reader.Expect("[", skipWhiteSpace: true);
                    if (reader.Peek().Value.StartsWith("F=") || reader.Peek().Value.StartsWith("B="))
                    {
                        reader.Advance();
                        var match = ColorSpecifierRegex.Match(reader.Current.Value);
                        if (match.Success == false) throw new FormatException($"Unexpected token {reader.Current.Value} at position {reader.Current.Position} ");

                        var isForeground = match.Groups["ForB"].Value == "F";

                        if (isForeground)
                        {
                            if (Enum.TryParse(match.Groups["color"].Value, out ConsoleColor c))
                            {
                                lastForeground = (RGB)c;
                            }
                            else if (RGB.TryParse(match.Groups["color"].Value, out lastForeground) == false)
                            {
                                throw new ArgumentException($"Expected a color @ {reader.Position}");
                            }
                        }
                        else
                        {
                            if (Enum.TryParse(match.Groups["color"].Value, out ConsoleColor c))
                            {
                                lastBackground = (RGB)c;
                            }
                            else if (RGB.TryParse(match.Groups["color"].Value, out lastBackground) == false)
                            {
                                throw new ArgumentException($"Expected a color @ {reader.Position}");
                            }
                        }

                        reader.Expect("]");
                    }
                    else
                    {
                        var match = PixelDiffRegex.Match(reader.Advance().Value);
                        if (match.Success == false) throw new FormatException("Could not parse pixel diff");

                        var valGroup = match.Groups["val"].Value;

                        char? nextChar = valGroup.Length == 1 ? valGroup[0] : valGroup == "OB" ? '[' : valGroup == "CB" ? ']' : new char?();
                        if (nextChar.HasValue == false) throw new FormatException($"Unexpected token {nextChar} @ {reader.Position}");

                        diffFrame.Diffs.Add(new ConsoleBitmapPixelDiff()
                        {
                            X = int.Parse(match.Groups["x"].Value),
                            Y = int.Parse(match.Groups["y"].Value),
                            Value = new ConsoleCharacter(nextChar.Value, lastForeground, lastBackground),
                        });

                        reader.Expect("]");
                    }
                }

                return diffFrame;
            }
            else
            {
                var rawFrame = new ConsoleBitmapRawFrame()
                {
                    Timestamp = timestamp,
                    Pixels = new ConsoleCharacter[width][]
                };

                for (var i = 0; i < width; i++)
                {
                    rawFrame.Pixels[i] = new ConsoleCharacter[height];
                }

                var x = 0;
                var y = 0;
                var lastFg = ConsoleString.DefaultForegroundColor;
                var lastBg = ConsoleString.DefaultBackgroundColor;
                while (reader.CanAdvance(skipWhitespace:true))
                {
                    reader.Expect("[", skipWhiteSpace:true);
                    var next = reader.Advance();
                    var match = ColorSpecifierRegex.Match(next.Value);
                    if (match.Success)
                    {  
                        var isForeground = match.Groups["ForB"].Value == "F";

                        if (isForeground)
                        {

                            if(Enum.TryParse<ConsoleColor>(match.Groups["color"].Value, out ConsoleColor c))
                            {
                                lastFg = c;
                            }
                            else if(RGB.TryParse(match.Groups["color"].Value, out lastFg) == false)
                            {
                                throw new ArgumentException($"Expected a color @ {reader.Position}");
                            }
                        }
                        else
                        {
                            if (Enum.TryParse<ConsoleColor>(match.Groups["color"].Value, out ConsoleColor c))
                            {
                                lastBg = c;
                            }
                            else if (RGB.TryParse(match.Groups["color"].Value, out lastBg) == false)
                            {
                                throw new ArgumentException($"Expected a color @ {reader.Position}");
                            }
                        }
                    }
                    else
                    {
                        char? nextChar = next.Value.Length == 1 ? next.Value[0] : next.Value == "OB" ? '[' : next.Value == "CB" ? ']' : new char?();
                        if (nextChar.HasValue == false) throw new FormatException($"Unexpected token {nextChar} @ {next.Position}");
                        rawFrame.Pixels[x][y++] = new ConsoleCharacter(nextChar.Value, lastFg, lastBg);
                        if (y == height)
                        {
                            y = 0;
                            x++;
                        }
                    }

                    reader.Expect("]");
                }

                return rawFrame;
            }
        }