runmat-runtime 0.4.1

Core runtime for RunMat with builtins, BLAS/LAPACK integration, and execution APIs
Documentation
{
  "title": "read",
  "category": "io/net",
  "keywords": [
    "read",
    "tcpclient",
    "networking",
    "socket",
    "binary data"
  ],
  "summary": "Read numeric or text data from a remote host through a MATLAB-compatible tcpclient struct.",
  "references": [
    "https://www.mathworks.com/help/matlab/ref/tcpclient.read.html"
  ],
  "gpu_support": {
    "elementwise": false,
    "reduction": false,
    "precisions": [],
    "broadcasting": "none",
    "notes": "All TCP reads run on the host CPU. GPU-resident arguments are gathered before any socket I/O; providers do not expose networking hooks."
  },
  "fusion": {
    "elementwise": false,
    "reduction": false,
    "max_inputs": 3,
    "constants": "inline"
  },
  "requires_feature": null,
  "tested": {
    "unit": "builtins::io::net::read::tests"
  },
  "description": "`read(t)` consumes data waiting on the TCP/IP client returned by `tcpclient` (or `accept`). The builtin mimics MATLAB’s behaviour for `read` so existing code that exchanges bytes with remote services behaves identically. It honours the client’s configured `Timeout`, respects the `ByteOrder` property when materialising multi-byte numeric types, and interprets the optional `datatype` argument just like MATLAB.",
  "behaviors": [
    "`data = read(t)` waits until at least one byte becomes available (subject to the client timeout) and then drains the socket buffer, returning a **row vector of doubles** whose values come from the received bytes. If the peer closes the connection without sending data, the result is an empty row vector.",
    "`data = read(t, count)` blocks until exactly `count` values are available (again honouring `Timeout`). When the peer closes the socket before satisfying the request the builtin raises `RunMat:read:ConnectionClosed`.",
    "`data = read(t, count, datatype)` interprets the values using the requested MATLAB datatype. Supported tokens mirror MATLAB: `\"uint8\"` (default), `\"int8\"`, `\"uint16\"`, `\"int16\"`, `\"uint32\"`, `\"int32\"`, `\"uint64\"`, `\"int64\"`, `\"single\"`, `\"double\"`, `\"char\"`, and `\"string\"`. Numeric outputs are returned as doubles; `\"char\"` produces a MATLAB-style character row vector and `\"string\"` returns a scalar string.",
    "Every call honours the client’s `ByteOrder` property when decoding multi-byte numbers. Little-endian is the default, but `\"big-endian\"` is respected for data written in network byte order.",
    "The builtin gathers GPU-resident arguments automatically, executes the socket read on the CPU, and returns host values.",
    "Errors are raised with MATLAB-compatible identifiers: invalid client structs trigger `RunMat:read:InvalidTcpClient`, timeouts emit `RunMat:read:Timeout`, and connection closures before a requested count is met raise `RunMat:read:ConnectionClosed`."
  ],
  "examples": [
    {
      "description": "Reading a fixed number of bytes from a TCP echo service",
      "input": "client = tcpclient(\"127.0.0.1\", 50000);\nwrite(client, uint8(1:6));\npayload = read(client, 6)",
      "output": "payload =\n     1     2     3     4     5     6"
    },
    {
      "description": "Reading ASCII text as characters",
      "input": "client = tcpclient(\"127.0.0.1\", 50001);\nwrite(client, \"RunMat TCP\");\nchars = read(client, 10, \"char\")",
      "output": "chars =\n    'RunMat TCP'"
    },
    {
      "description": "Reading doubles written in big-endian byte order",
      "input": "client = tcpclient(\"localhost\", 50002, \"ByteOrder\", \"big-endian\");\nwrite(client, swapbytes([1 2 3], \"double\"));\nvalues = read(client, 3, \"double\")",
      "output": "values =\n     1     2     3"
    },
    {
      "description": "Reading all available data without specifying a count",
      "input": "client = tcpclient(\"127.0.0.1\", 50003);\nwrite(client, uint8([10 20 30]));\nburst = read(client)",
      "output": "burst =\n    10    20    30"
    },
    {
      "description": "Handling read timeouts gracefully",
      "input": "client = tcpclient(\"example.com\", 12345, \"Timeout\", 0.5);\ntry\n    data = read(client, 64);\ncatch err\n    disp(err.identifier)\nend",
      "output": "RunMat:read:Timeout"
    }
  ],
  "faqs": [
    {
      "question": "Does `read` modify the client struct?",
      "answer": "No. The builtin interacts with the socket stored in RunMat’s internal registry. The visible struct returned from `tcpclient` is passed by value and is not mutated in place."
    },
    {
      "question": "What happens when the remote host closes the connection?",
      "answer": "If the peer closes the connection before the requested count is satisfied, `read` raises `RunMat:read:ConnectionClosed`. When no specific count is requested (`read(t)`), the builtin returns whatever data was available before the closure (possibly an empty vector)."
    },
    {
      "question": "Does `read` support infinite timeouts?",
      "answer": "Yes. Setting `t.Timeout = Inf` (or passing `\"Timeout\", inf` when constructing the client) leaves the socket in blocking mode. The builtin waits indefinitely until enough data arrives or the peer closes the connection."
    },
    {
      "question": "How are multibyte integers decoded?",
      "answer": "RunMat honours the client’s `ByteOrder` property (`\"little-endian\"` or `\"big-endian\"`). For example, `read(t, 4, \"uint16\")` consumes eight bytes and interprets each pair in the configured byte order."
    },
    {
      "question": "Can I read UTF-8 strings directly?",
      "answer": "Use the `\"string\"` datatype. The builtin converts each received byte directly into a MATLAB string scalar assuming UTF-8 (non-UTF-8 sequences fall back to byte-wise decoding)."
    }
  ],
  "links": [
    {
      "label": "tcpclient",
      "url": "./tcpclient"
    },
    {
      "label": "accept",
      "url": "./accept"
    },
    {
      "label": "write",
      "url": "./write"
    },
    {
      "label": "readline",
      "url": "./readline"
    },
    {
      "label": "close",
      "url": "./close"
    },
    {
      "label": "tcpserver",
      "url": "./tcpserver"
    }
  ],
  "source": {
    "label": "`crates/runmat-runtime/src/builtins/io/net/read.rs`",
    "url": "https://github.com/runmat-org/runmat/blob/main/crates/runmat-runtime/src/builtins/io/net/read.rs"
  },
  "gpu_behavior": [
    "Networking is a host-only subsystem. When a client struct or argument arrives from the GPU, RunMat gathers the value back to the CPU before reading from the socket. No acceleration-provider hooks participate in the operation, and the result is always a host value (double tensor, char array, or string). Future GPU providers continue to gather metadata automatically so networking remains CPU-bound."
  ]
}