public static void WriteDatum(this BinaryWriter w, Datum d) { SymbolCollector sc = new SymbolCollector(); SetDatum symbols = d.Visit(sc); MutableBoxCollector mc = new MutableBoxCollector(); SetDatum mutableBoxes = d.Visit(mc); DictionaryDatum symbolMap = DictionaryDatum.Empty; ListDatum uninternedSymbols = ListDatum.Empty; ListDatum internedSymbols = ListDatum.Empty; DictionaryDatum mutableBoxMap = DictionaryDatum.Empty; foreach (SymbolDatum s in symbols.Cast <SymbolDatum>()) { if (s.IsInterned) { internedSymbols = internedSymbols.Add(s); } else { uninternedSymbols = uninternedSymbols.Add(s); } } w.Write(uninternedSymbols.Count); foreach (int i in Enumerable.Range(0, uninternedSymbols.Count)) { symbolMap = symbolMap.Add(uninternedSymbols[i], new IntDatum((BigInteger)(~i))); } w.Write(internedSymbols.Count); foreach (int i in Enumerable.Range(0, internedSymbols.Count)) { symbolMap = symbolMap.Add(internedSymbols[i], new IntDatum((BigInteger)i)); w.Write(((SymbolDatum)(internedSymbols[i])).Name); } w.Write(mutableBoxes.Count); foreach (int i in Enumerable.Range(0, mutableBoxes.Count)) { mutableBoxMap = mutableBoxMap.Add(mutableBoxes[i], new IntDatum((BigInteger)i)); } BinaryWriteVisitor v = new BinaryWriteVisitor(w, symbolMap, mutableBoxMap); foreach (int i in Enumerable.Range(0, mutableBoxes.Count)) { ((MutableBoxDatum)mutableBoxes[i]).Content.Visit(v); } d.Visit(v); }
public static Datum ReadDatum(this BinaryReader r) { int uninternedSymbolCount = r.ReadInt32(); ListDatum uninternedSymbols = ListDatum.Empty; for (int i = 0; i < uninternedSymbolCount; ++i) { uninternedSymbols = uninternedSymbols.Add(new SymbolDatum()); } int internedSymbolCount = r.ReadInt32(); ListDatum internedSymbols = ListDatum.Empty; for (int i = 0; i < internedSymbolCount; ++i) { string name = r.ReadString(); internedSymbols = internedSymbols.Add(new SymbolDatum(name)); } int mutableBoxCount = r.ReadInt32(); ListDatum mutableBoxes = ListDatum.Empty; for (int i = 0; i < mutableBoxCount; ++i) { mutableBoxes = mutableBoxes.Add(new MutableBoxDatum(NullDatum.Value)); } Func <Datum> read = null; read = delegate() { byte typeId = r.ReadByte(); switch (typeId) { case B_NULL: return(NullDatum.Value); case B_BOOLEAN_FALSE: return(BooleanDatum.False); case B_BOOLEAN_TRUE: return(BooleanDatum.True); case B_CHAR: { char ch = r.ReadChar(); return(new CharDatum(ch)); } case B_STRING: { string str = r.ReadString(); return(new StringDatum(str)); } case B_INT: { BigInteger b = r.ReadBigInteger(); return(new IntDatum(b)); } case B_FLOAT: { double f = r.ReadDouble(); return(new FloatDatum(f)); } case B_BYTE_ARRAY: { int nBytes = r.ReadInt32(); byte[] buf = new byte[nBytes]; int bytesRead = r.Read(buf, 0, nBytes); if (bytesRead != nBytes) { throw new EndOfStreamException(); } return(ByteArrayDatum.FromByteArray(buf)); } case B_SYMBOL: { int index = r.ReadInt32(); if (index < 0) { return(uninternedSymbols[~index]); } else { return(internedSymbols[index]); } } case B_LIST: { int count = r.ReadInt32(); ListDatum l = ListDatum.Empty; foreach (int i in Enumerable.Range(0, count)) { l = l.Add(read()); } return(l); } case B_SET: { int count = r.ReadInt32(); SetDatum s = SetDatum.Empty; foreach (int i in Enumerable.Range(0, count)) { s = s.Add(read()); } return(s); } case B_DICTIONARY: { int count = r.ReadInt32(); DictionaryDatum d = DictionaryDatum.Empty; foreach (int i in Enumerable.Range(0, count)) { Datum k = read(); Datum v = read(); d = d.Add(k, v); } return(d); } case B_MUTABLE_BOX: { int index = r.ReadInt32(); return(mutableBoxes[index]); } case B_RATIONAL: { BigInteger numerator = r.ReadBigInteger(); BigInteger denominator = r.ReadBigInteger(); return(new RationalDatum(new BigRational(numerator, denominator))); } case B_GUID: { byte[] buf = new byte[16]; int bytesRead = r.Read(buf, 0, 16); if (bytesRead < 16) { throw new EndOfStreamException(); } return(new GuidDatum(new Guid(buf))); } default: throw new FormatException("Unknown type id"); } }; for (int j = 0; j < mutableBoxCount; ++j) { ((MutableBoxDatum)mutableBoxes[j]).Content = read(); } return(read()); }