Table of Contents

Learning path

Start with one small header and keep using it until you can explain every byte. You need basic programming, not experience with binary formats. A declaration describes where values live; it does not prove that an entire file is valid. CStructSharp uses a C-like layout language, not a complete C compiler or your machine's native C memory-layout rules.

One complete first journey

Follow these steps in the same console project. The pages include complete programs; replace Program.cs when instructed rather than combining several top-level programs in one file. JavaScript readers can follow the equivalent browser and Node starter, which uses the same header and operations.

Step Do this Check your understanding before continuing
1. Install and read Follow install and first parse. Run the six-byte program. Explain why kind is 2 and length is 6, and why the second field starts at byte offset 2.
2. Predict and recover Change the first byte to 03, then try the short input in the header continuation. Restore complete input and read again. Distinguish a valid changed value from missing bytes. A failed read does not supply a usable result.
3. Create bytes Run Next.cs in the same continuation. Compare Created with the original six bytes. Explain that serialization creates bytes from values; a C# class's own memory layout does not decide the wire layout.
4. Change one field Follow change existing bytes. Compare the original and updated bytes. Identify the two-byte slot that can change and the four bytes that must stay unchanged. An update cannot insert space.
5. Choose realistic limits Read variables, options and limits, then errors and recovery. Explain why an element limit differs from a byte limit, and why successful header parsing does not validate a whole format.

An offset counts bytes from an origin, starting at zero. The first example's origin is the beginning of its input array. Passing a slice gives that slice its own zero; file offsets and mapped-memory addresses need the explicit origins explained in debug ranges and addresses. Do not add a file offset twice when turning a returned range into a UI selection.

Array limits count elements: ten uint32 values are ten elements but forty bytes. String limits count encoded bytes, not displayed characters. A total-read budget counts parser reads, including repeated pointer visits, not the distance of a seek or the physical file's length. Raising a budget does not make a large result cheap.

After step 4, choose an optional branch:

  • Fixed layout in your source: generate the same header. Compare its typed result with the runtime result. Generation moves layout work to build time; it is not required to parse.
  • Memory images with addresses: start with memory and stored data, then analyze mapped memory. First explain how a virtual address maps to bytes in a file. The executable example works with a synthetic image; it does not attach to or change a live process.
  • Inspect a real file: use the desktop inspector. Its catalog describes supported header structures, not full decoders. Changing bytes, schema or settings invalidates the previous result; run again before trusting field ranges. Edits are temporary, with no export, and need a browser width of at least 1200 CSS pixels.

Continue by topic

These pages extend the journey. Skip questions you can already answer.

  1. What it is. Binary layout basics: bytes, offsets, widths, byte order, padding, and what a CStruct adds to them.
  2. Install. Install and make a first parse - a console project and six bytes (JavaScript readers: the Node.js and browser quick start instead).
  3. First parse. Continue with the header: the same header created, changed, and read into a class, and what a short input does.
  4. Read. Read values and paths, then typed values when application code wants a C# class or a checked scalar; choose an API when the input is a stream, a span, or memory; trimming and Native AOT before a trimmed or AOT publish.
  5. Modify and write. Write and serialize values and update existing data.
  6. Layout features. Strings, enums, unions, pointers, conditional fields, and binary metadata types; the language tutorial teaches the syntax behind them.
  7. Errors, files, and streams. Errors and recovery, variables, options, and limits, async reads, cancellation, and pipelines for streams that arrive while the program runs, and the binary file walkthrough, which combines reading, validating, and patching a file.
  8. JavaScript. The JavaScript API, large files and streams, and deployment.
  9. Reference and advanced. The layout-language manual, the C# API reference, performance, spans and buffer writers, debug ranges and addresses, and the memory-image series starting at analyze mapped memory.

Four examples to read first

Choose from the tested recipe catalog and the browser lessons. Read these four examples first; together they cover reading, writing, updating, typed results, and a data-dependent shape:

Example What it shows
starter/Program.cs (the README program) Parse six bytes and read two typed members.
starter/Next.cs Serialize from a class, update one field in place, read into a class, and handle a truncated input with TryReadValue.
starter/Generated.cs The same header as a [CStructLayout] class: typed Parse, Serialize, a view, and a typed setter, generated at build time.
Supply a runtime array count A count-prefixed payload: a caller-supplied variable sizes the array, and GetArrayLength reports the count without decoding the payload.

For JavaScript the equivalent is the standalone starter's app.js, which reads, writes, updates, and rereads the same header with parse, serialize, and update.

Background reading for anyone new to native data: how C structs occupy memory and memory addresses and stored data. The glossary defines the terms the guides use.