Streamの一部を取り出すため、別のStreamでラップしてみました。C#とF#の両方のコードをパブリックドメインで貼っておきます。C#とF#の対比や、カスタムStreamの例として使えるのではないかと思います。F#の構文はC#と掛け離れていますが、簡潔なので慣れれば便利そうです。
// C# using System; using System.IO; public class SubStream : Stream { private Stream s; private long start, length, pos; public SubStream(Stream s, long length) { this.s = s; this.start = s.Position; this.length = length; } public override long Length { get { return length; } } public override bool CanRead { get { return pos < length; } } public override bool CanWrite { get { return false; } } public override bool CanSeek { get { return true; } } public override void Flush() { } public override long Position { get { return pos; } set { s.Position = start + (pos = value); } } public override int Read(byte[] buffer, int offset, int count) { if (!CanRead) return 0; count = (int)Math.Min(length - pos, count); int ret = s.Read(buffer, offset, count); pos += ret; return ret; } public override long Seek(long offset, SeekOrigin origin) { switch (origin) { case SeekOrigin.Begin: Position = offset; break; case SeekOrigin.Current: Position += offset; break; case SeekOrigin.End: Position = length + offset; break; } return pos; } public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } public override void SetLength(long value) { throw new NotImplementedException(); } }
// F# open System open System.IO type SubStream(s:Stream, length:int64) = inherit Stream() let start = s.Position let mutable pos = 0L override x.Length = length override x.CanRead = pos < length override x.CanWrite = false override x.CanSeek = true override x.Flush() = () override x.Position with get() = pos and set(v) = pos <- v s.Position <- start + pos override x.Read(buffer, offset, count) = if not x.CanRead then 0 else let count' = int <| Math.Min(length - pos, int64 count) let ret = s.Read(buffer, offset, count') pos <- pos + (int64 ret) ret override x.Seek(offset, origin) = match origin with | SeekOrigin.Begin -> x.Position <- offset | SeekOrigin.Current -> x.Position <- pos + offset | SeekOrigin.End -> x.Position <- length + offset | _ -> () pos override x.Write(_, _, _) = raise <| new NotImplementedException() override x.SetLength(_) = raise <| new NotImplementedException()