Skip to main content
Version: 0.1.5
Docs.rs: ironrdp-core

Overview

The ironrdp-core crate provides foundational traits and types used throughout IronRDP. It defines the core encoding/decoding infrastructure, cursor utilities, and error types that form the basis of all PDU operations.

Key Design Principles

  • no_std compatible: Core functionality works without the standard library
  • Object-safe traits: Enables dynamic dispatch for protocol PDUs
  • Zero-copy parsing: Uses cursors instead of allocating intermediate buffers
  • Type-safe encoding: Size is computed before writing to prevent buffer overruns

Core Traits

Encode

Trait for types that can be encoded into binary form. All RDP PDUs implement this trait. Key Methods:
  • encode() - Writes the PDU to a WriteCursor
  • name() - Returns a static name for debugging/logging
  • size() - Computes the exact size in bytes before encoding
Helper Functions:

Decode

Trait for types that can be decoded from a byte stream. The lifetime parameter 'de allows zero-copy parsing. Helper Functions:

DecodeOwned

Similar to Decode but unconditionally returns an owned type (no lifetime parameter). Use when you need to own the decoded data.

Cursor Types

ReadCursor

Zero-copy cursor for reading bytes from a buffer. Tracks position and provides typed read methods. Common Methods:
fn(bytes: &'a [u8]) -> Self
Create a new cursor from a byte slice
fn(&mut self) -> u8
Read a single byte
fn(&mut self) -> u16
Read a little-endian u16
fn(&mut self) -> u16
Read a big-endian u16
fn(&mut self) -> u32
Read a little-endian u32
fn(&mut self, n: usize) -> &'a [u8]
Read a slice of n bytes
fn(&self) -> &'a [u8]
Get the remaining unread bytes
fn(&self) -> usize
Number of bytes remaining
fn(&self) -> usize
Current position in the buffer
Example:

WriteCursor

Cursor for writing bytes to a mutable buffer. Provides type-safe write methods and tracks position. Common Methods:
fn(bytes: &'a mut [u8]) -> Self
Create a new cursor from a mutable byte slice
fn(&mut self, value: u8)
Write a single byte
fn(&mut self, value: u16)
Write a little-endian u16
fn(&mut self, value: u16)
Write a big-endian u16
fn(&mut self, value: u32)
Write a little-endian u32
fn(&mut self, slice: &[u8])
Write a slice of bytes
fn(&self) -> usize
Current position (number of bytes written)
Example:

WriteBuf

Growable write buffer that manages a Vec<u8> internally. Maintains separate “filled” and “unfilled” regions.
Requires the alloc feature. Use WriteBuf when the output size is not known in advance.
Common Methods:
fn() -> Self
Create a new empty buffer
fn(&mut self, size: usize) -> &mut [u8]
Get a mutable slice of at least size bytes, growing if necessary
fn(&mut self, n: usize)
Mark n bytes as filled after writing to unfilled_to()
fn(&self) -> &[u8]
Get the filled portion of the buffer
fn(&mut self)
Reset the filled region without deallocating
Example:

Error Types

EncodeError & DecodeError

Both encode and decode operations return structured errors with context. Example Error Handling:

Features

feature
Enables standard library support (includes alloc)
feature
Enables heap allocations (WriteBuf, Vec support)

Usage Notes

WriteCursor vs WriteBuf:
  • Use WriteCursor when you know the exact size and want syscall-free, infallible writes
  • Use WriteBuf when size is unknown and you need the buffer to grow automatically
  • WriteCursor wraps &mut [u8] for stack/static buffers
  • WriteBuf manages Vec<u8> internally and can resize
Object Safety:
The Encode trait is intentionally object-safe to enable dynamic dispatch:

See Also