public object Deserialize(IStorage storage, Data.Node data, object result) { Kean.Collection.IList<Data.Node> nodes; Reflect.Type type; Reflect.Type elementType; type = data.Type; elementType = this.GetElementType(type); if (data is Data.Collection) nodes = (data as Data.Collection).Nodes; else { // only one element so it was impossible to know it was a collection nodes = new Kean.Collection.List<Data.Node>(data); data.Type = data.OriginalType ?? elementType; Uri.Locator locator = data.Locator.Copy(); locator.Fragment += "0"; data.Locator = locator; } if (result.IsNull()) result = this.Create(type, elementType, nodes.Count); int i = 0; foreach (Data.Node child in nodes) { int c = i++; // ensure c is unique in every closure of lambda function below storage.Deserialize(child, elementType, d => this.Set(result, d, c)); } return result; }
public Data.Node Store(Storage storage, Data.Node data) { if (data is Data.Branch) { Kean.Collection.IList<Data.Node> nodes = new Kean.Collection.List<Data.Node>(); foreach (Data.Node child in (data as Data.Branch).Nodes) if (child is Data.Collection) foreach (Data.Node c in (child as Data.Collection).Nodes) nodes.Add(c); else nodes.Add(child); (data as Data.Branch).Nodes.Clear(); foreach (Data.Node node in nodes) (data as Data.Branch).Nodes.Add(this.Store(storage, node)); } return data; }
void Filter() { byte? result = this.backend.Read(); if (result.HasValue) switch ((Command)result.Value) { case Command.SE: // End of subnegotiation parameters break; case Command.NOP: // No operation break; case Command.DM: // Data mark break; case Command.BRK: // Break break; case Command.IP: // Suspend break; case Command.AO: // Abort output break; case Command.AYT: // Are you there break; case Command.EC: // Erase character break; case Command.EL: // Erase line break; case Command.GA: // Go ahead break; case Command.SB: // Subnegotiation this.backend.Read(); // option this.backend.Read(); // supplied (0) / required (1) Collection.List<byte> value = new Kean.Collection.List<byte>(); byte? v; while ((v = this.backend.Read()).HasValue && (Command)v.Value != Command.IAC) value.Add(v.Value); this.backend.Read(); // SE break; case Command.WILL: // Will { byte? option = this.backend.Read(); // option if (option.HasValue) switch ((Option)option.Value) { case Option.WindowSize: case Option.TerminalType: default: this.backend.Write(new byte[] { (byte)Command.IAC, (byte)Command.WONT, option.Value }); break; case Option.TerminalSpeed: this.backend.Write(new byte[] { (byte)Command.IAC, (byte)Command.SB, option.Value, 1, (byte)Command.IAC, (byte)Command.SE }); break; case Option.SuppressGoAhead: this.backend.Write(new byte[] { (byte)Command.IAC, (byte)Command.DO, option.Value }); break; } } break; case Command.WONT: // Wont this.backend.Read(); // option break; case Command.DO: // Do { byte? option = this.backend.Read(); // option if (option.HasValue) switch ((Option)option.Value) { case Option.WindowSize: case Option.TerminalSpeed: case Option.TerminalType: default: this.backend.Write(new byte[] { (byte)Command.IAC, (byte)Command.WONT, option.Value }); break; case Option.Echo: case Option.SuppressGoAhead: if (!this.echo.HasValue || !this.echo.Value) this.backend.Write(new byte[] { (byte)Command.IAC, (byte)Command.WILL, option.Value }); this.echo = true; break; } } break; case Command.DONT: // Dont { byte? option = this.backend.Read(); // option if (option.HasValue) switch ((Option)option.Value) { case Option.Echo: case Option.SuppressGoAhead: if (!this.echo.HasValue || this.echo.Value) this.backend.Write(new byte[] { (byte)Command.IAC, (byte)Command.WONT, option.Value }); this.echo = false; break; } } break; case Command.IAC: // Interpret as command this.Filter(); break; } }