Skip to Content

Streamfab.keepstreams.generic.hook-smeagol-ther... (2024)

public void Dispose(IHookContext ctx) /* free any unmanaged resources */

// 3. Post‑hook (e.g., logging, decryption, metrics) await _hook.AfterReadAsync(_ctx, destination.Slice(0, bytesRead), cancellationToken) .ConfigureAwait(false);

public sealed class LoggingHook : IStreamHook { public void BeforeRead(IHookContext ctx, byte[] buffer, int offset, int count) => Console.WriteLine($"[LOG] About to read

private readonly Stream _inner; private readonly THook _hook; private readonly IHookContext _ctx; // … StreamFab.KeepStreams.Generic.Hook-Smeagol-TheR...

// Async overloads (optional but recommended) public ValueTask BeforeReadAsync(IHookContext ctx, Memory<byte> destination, CancellationToken ct) => default; public ValueTask AfterReadAsync(IHookContext ctx, ReadOnlyMemory<byte> data, CancellationToken ct) => default; // … similar for Write, Seek, etc.

// Then the inner stream is disposed (unless the hook says otherwise) _inner.Dispose(); base.Dispose(disposing);

You can subscribe using:

Typical overhead for a (i.e., a hook that just forwards everything) is ≈ 30–50 ns per call on modern .NET runtimes – negligible for most I/O‑bound workloads. Real‑world hooks (logging, encryption, compression) dominate the cost, not the wrapper. 7. Debugging & diagnostics HookSmeagol ships with a built‑in diagnostic source ( System.Diagnostics.DiagnosticListener ) named "StreamFab.KeepStreams.HookSmeagol" . It emits the following events:

// 2. Actual read from inner stream int bytesRead = await _inner.ReadAsync(destination, cancellationToken) .ConfigureAwait(false);

return bytesRead;

using System; using System.IO; using System.IO.Compression; using System.Threading.Tasks; using StreamFab.KeepStreams.Generic;

(The exact name you gave is truncated, so the description is written to cover the most common “Hook‑Smeagol” implementation that lives inside the StreamFab.KeepStreams.Generic namespace.) Hook‑Smeagring (often abbreviated simply as Smeagol ) is a generic, stream‑interception hook that lives in the KeepStreams library. Its primary responsibilities are:

The pattern mirrors Read ; the hook receives the buffer before the inner write and again after the write completes. 3.4 Seek , SetLength , Flush All these methods follow the same pre‑hook → inner operation → post‑hook flow. The async variants are implemented using ValueTask when possible to avoid allocations. 3.5 Disposal protected override void Dispose(bool disposing) public void Dispose(IHookContext ctx) /* free any unmanaged

// 1. Hook gets a chance to modify the request (e.g., apply a read‑limit) _hook.BeforeRead(_ctx, buffer, offset, count);

public void BeforeRead(IHookContext ctx, byte[] buffer, int offset, int count) /* … */ public void AfterRead(IHookContext ctx, byte[] buffer, int offset, int bytesRead) /* … */