public CDIItem ReadItem()
            {
                long nextIndex = Index;

                // Read the CDIBaseInfo header
                byte version = ReadByte();

                if (version != CDIVERSION)
                {
                    throw new FormatException("Got unexpected CDIBaseInfo version at " + Index);
                }
                byte kind = ReadByte();

                SkipPadding(4);
                uint size = ReadUInt32();

                nextIndex += size;

                CDIItem item = null;

                // Read kind-specific data
                switch ((CDIKind)kind)
                {
                case CDIKind.UsingInfo:
                    ushort   cUsings  = ReadUInt16();
                    CDIUsing cdiUsing = new CDIUsing();
                    cdiUsing.countOfUsing = new int[cUsings];
                    for (ushort j = 0; j < cUsings; j++)
                    {
                        cdiUsing.countOfUsing[j] = ReadUInt16();
                    }
                    SkipPadding(4);
                    item = cdiUsing;
                    break;

                case CDIKind.ForwardInfo:
                    uint       tokenToForwardTo = ReadUInt32();
                    CDIForward fwd = new CDIForward();
                    fwd.tokenToForwardTo = Util.AsToken((int)tokenToForwardTo);
                    item = fwd;
                    break;

                case CDIKind.ForwardToModuleInfo:
                    uint             token  = ReadUInt32();
                    CDIForwardModule modFwd = new CDIForwardModule();
                    modFwd.tokenOfModuleInfo = Util.AsToken((int)token);
                    item = modFwd;
                    break;

                case CDIKind.IteratorLocals:
                    int cBuckets = ReadInt32();
                    if (cBuckets < 0)
                    {
                        throw new FormatException("Unexpected negative iteratorLocal bucket count at " + BaseStream.Position);
                    }
                    CDIIteratorLocals iterLocals = new CDIIteratorLocals();
                    iterLocals.buckets = new CDIIteratorLocalBucket[cBuckets];
                    for (int j = 0; j < cBuckets; j++)
                    {
                        CDIIteratorLocalBucket b = new CDIIteratorLocalBucket();
                        b.ilOffsetStart       = ReadInt32();
                        b.ilOffsetEnd         = ReadInt32();
                        iterLocals.buckets[j] = b;
                    }
                    item = iterLocals;
                    break;

                case CDIKind.ForwardIterator:
                    CDIForwardIterator fwdIter = new CDIForwardIterator();
                    fwdIter.iteratorClassName = ReadString();
                    SkipPadding(4);
                    item = fwdIter;
                    break;

                default:
                    CDIUnknown u = new CDIUnknown();
                    u.kind = kind;
                    byte[] bytes = ReadBytes(checked ((int)(nextIndex - Index)));
                    u.bytes = Util.ToHexString(bytes);
                    item    = u;
                    break;
                }

                if (Index != nextIndex)
                {
                    throw new FormatException(String.Format("Expected CDI item to end at index {0}, but ended at {1} instead", nextIndex, Index));
                }
                item.version = version;
                return(item);
            }
            private void WriteItem(CDIItem item)
            {
                long startPos = BaseStream.Position;
                uint length   = 2 * sizeof(int);

                Write((byte)item.version);

                if (item is CDIUsing)
                {
                    CDIUsing cdiUsing = (CDIUsing)item;
                    Write((byte)CDIKind.UsingInfo);
                    WritePadding(4);
                    length = AlignUp(8 + ((uint)cdiUsing.countOfUsing.Length + 1) * sizeof(ushort), 4);
                    Write(length);
                    Write(checked ((ushort)cdiUsing.countOfUsing.Length));
                    foreach (ushort u in cdiUsing.countOfUsing)
                    {
                        Write(u);
                    }
                    WritePadding(4);
                }
                else if (item is CDIForward)
                {
                    CDIForward cdiFwd = (CDIForward)item;
                    Write((byte)CDIKind.ForwardInfo);
                    WritePadding(4);
                    length = 12;
                    Write(length);
                    Write(Util.ToInt32(cdiFwd.tokenToForwardTo, 16));
                }
                else if (item is CDIForwardModule)
                {
                    CDIForwardModule cdiFwdMod = (CDIForwardModule)item;
                    Write((byte)CDIKind.ForwardToModuleInfo);
                    WritePadding(4);
                    length = 12;
                    Write(length);
                    Write(Util.ToInt32(cdiFwdMod.tokenOfModuleInfo, 16));
                }
                else if (item is CDIIteratorLocals)
                {
                    CDIIteratorLocals cdiIterLocals = (CDIIteratorLocals)item;
                    Write((byte)CDIKind.IteratorLocals);
                    WritePadding(4);
                    length = (uint)(12 + cdiIterLocals.buckets.Length * 2 * sizeof(uint));
                    Write(length);
                    Write(cdiIterLocals.buckets.Length);
                    foreach (CDIIteratorLocalBucket b in cdiIterLocals.buckets)
                    {
                        Write(b.ilOffsetStart);
                        Write(b.ilOffsetEnd);
                    }
                }
                else if (item is CDIForwardIterator)
                {
                    CDIForwardIterator cdiIter = (CDIForwardIterator)item;
                    Write((byte)CDIKind.ForwardIterator);
                    WritePadding(4);
                    length = AlignUp(8 + 2 * ((uint)cdiIter.iteratorClassName.Length + 1), 4);
                    Write(length);
                    WriteString(cdiIter.iteratorClassName);
                    WritePadding(4);
                }
                else if (item is CDIUnknown)
                {
                    CDIUnknown cdiUnknown = (CDIUnknown)item;
                    Write((byte)cdiUnknown.kind);
                    WritePadding(4);
                    byte[] bytes = Util.ToByteArray(cdiUnknown.bytes);
                    length = 8 + (uint)bytes.Length;
                    Write(length);
                    Write(bytes);
                }
                else
                {
                    Debug.Assert(false, "Unexpected CDIItem type");
                }

                Debug.Assert(BaseStream.Position == startPos + length, "Didn't write the length we promised");
            }