public static async Task <ChessBoard> FromStreamAsync(Stream stream) { bool?hasStarted = null; string[] playerNames = new string[2]; PlayerColor[] playerColors = new PlayerColor[2]; int playersReceived = 0; string winner = null; double? turnTimeLeft = null; List <string> moves = new List <string>(); var settings = new XmlReaderSettings() { Async = true }; using (var xml = XmlReader.Create(stream, settings)) while (await xml.ReadAsync()) { if (!xml.IsStartElement()) { continue; } if (xml.Name == "Game") { if (hasStarted != null) { throw new InvalidDataException(); } hasStarted = xml.GetAttribute("HasStarted") == "true"; winner = xml.GetAttribute("Winner"); } else if (xml.Name == "Player") { if (playersReceived >= 2) { throw new InvalidDataException(); } playerNames[playersReceived] = xml.GetAttribute("Name"); playerColors[playersReceived] = xml.GetAttribute("Color") == "Black" ? PlayerColor.Black : PlayerColor.White; playersReceived++; } else if (xml.Name == "Turn") { if (turnTimeLeft != null) { throw new InvalidDataException(); } string timeLeftString = xml.GetAttribute("TimeLeft"); if (!double.TryParse(timeLeftString, out double timeLeftDouble)) { throw new InvalidDataException("Invalid turn element!"); } turnTimeLeft = timeLeftDouble; } else if (xml.Name == "Board") { while (await xml.ReadAsync()) { if (!xml.IsStartElement("Move")) { break; } moves.Add(await xml.ReadElementContentAsStringAsync()); } } else { throw new InvalidDataException("Invalid ChessBoard xml!"); } } if (hasStarted == null) { throw new InvalidDataException(); } //If the game hasn't started, just return an empty ChessBoard if (!hasStarted.Value) { return(new ChessBoard()); } //Validate input when the game has started... if (playersReceived != 2) { throw new InvalidDataException(); } if (playerNames.Any(name => string.IsNullOrWhiteSpace(name))) { throw new InvalidDataException(); } if (!playerColors.Any(color => color == PlayerColor.White) || !playerColors.Any(color => color == PlayerColor.Black)) { throw new InvalidDataException(); } string whiteName = playerColors[0] == PlayerColor.White ? playerNames[0] : playerNames[1]; string blackName = playerColors[0] == PlayerColor.White ? playerNames[1] : playerNames[0]; if (!string.IsNullOrWhiteSpace(winner)) { return(new ChessBoard(whiteName, blackName, winner, moves.ToArray())); } //Validate input when the game hasn't ended yet... if (turnTimeLeft == null) { throw new InvalidDataException(); } return(new ChessBoard(whiteName, blackName, turnTimeLeft.Value, moves.ToArray())); }