or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compression.mdcore-io.mdfilesystem.mdhashing.mdindex.mdutilities.md

utilities.mddocs/

0

# Utilities and Extensions

1

2

This document covers Okio's helper functions, timeout management, advanced buffer operations, selection utilities, and platform-specific extensions.

3

4

## Timeout Management

5

6

Timeout provides configurable timeout policies for I/O operations, allowing you to set deadlines and prevent operations from blocking indefinitely.

7

8

### Timeout Class

9

10

```kotlin { .api }

11

expect open class Timeout {

12

// Timeout configuration

13

fun timeout(timeout: Long, unit: TimeUnit): Timeout

14

fun deadlineNanoTime(deadlineNanoTime: Long): Timeout

15

fun clearTimeout(): Timeout

16

fun clearDeadline(): Timeout

17

18

// Timeout checking

19

fun hasDeadline(): Boolean

20

fun deadlineNanoTime(): Long

21

fun timeoutNanos(): Long

22

23

// Timeout enforcement

24

fun throwIfReached()

25

fun waitUntilNotified(monitor: Any)

26

27

companion object {

28

val NONE: Timeout // Timeout that never times out

29

}

30

}

31

```

32

33

### Usage Examples

34

35

```kotlin

36

// Basic timeout configuration

37

val timeout = Timeout()

38

.timeout(5, TimeUnit.SECONDS)

39

.deadlineNanoTime(System.nanoTime() + TimeUnit.MINUTES.toNanos(1))

40

41

// Check timeout status

42

if (timeout.hasDeadline()) {

43

val remainingTime = timeout.deadlineNanoTime() - System.nanoTime()

44

println("Time remaining: ${remainingTime / 1_000_000}ms")

45

}

46

47

// Using timeout with I/O operations

48

val fs = FileSystem.SYSTEM

49

val path = "/tmp/large-file.txt".toPath()

50

51

try {

52

val source = fs.source(path)

53

source.timeout().timeout(30, TimeUnit.SECONDS)

54

55

source.buffer().use { bufferedSource ->

56

while (!bufferedSource.exhausted()) {

57

// This will throw if timeout is exceeded

58

val data = bufferedSource.readByteString(8192)

59

processData(data)

60

}

61

}

62

} catch (e: IOException) {

63

if (e.message?.contains("timeout") == true) {

64

println("Operation timed out")

65

} else {

66

println("I/O error: ${e.message}")

67

}

68

}

69

```

70

71

### Custom Timeout Implementations

72

73

```kotlin

74

// Monitor long-running operation with timeout

75

fun monitoredOperation(operation: () -> Unit, timeoutSeconds: Long) {

76

val timeout = Timeout().timeout(timeoutSeconds, TimeUnit.SECONDS)

77

val startTime = System.nanoTime()

78

79

try {

80

operation()

81

val duration = (System.nanoTime() - startTime) / 1_000_000

82

println("Operation completed in ${duration}ms")

83

} catch (e: Exception) {

84

timeout.throwIfReached()

85

throw e

86

}

87

}

88

```

89

90

## Selection and Matching

91

92

Okio provides efficient selection mechanisms for matching byte sequences from streams.

93

94

### Options Class

95

96

```kotlin { .api }

97

class Options private constructor() : List<ByteString> {

98

override val size: Int

99

override fun get(index: Int): ByteString

100

override fun iterator(): Iterator<ByteString>

101

102

companion object {

103

fun of(vararg byteStrings: ByteString): Options

104

}

105

}

106

```

107

108

### TypedOptions Class

109

110

```kotlin { .api }

111

class TypedOptions<T : Any> private constructor() : List<T> {

112

override val size: Int

113

override fun get(index: Int): T

114

115

companion object {

116

inline fun <T : Any> of(

117

values: Iterable<T>,

118

encode: (T) -> ByteString

119

): TypedOptions<T>

120

}

121

}

122

```

123

124

### BufferedSource Selection Methods

125

126

```kotlin { .api }

127

expect sealed interface BufferedSource {

128

// Selection operations

129

fun select(options: Options): Int

130

fun <T : Any> select(options: TypedOptions<T>): T?

131

}

132

```

133

134

### Selection Usage Examples

135

136

```kotlin

137

// HTTP method parsing

138

val httpMethods = Options.of(

139

"GET".encodeUtf8(),

140

"POST".encodeUtf8(),

141

"PUT".encodeUtf8(),

142

"DELETE".encodeUtf8(),

143

"PATCH".encodeUtf8()

144

)

145

146

fun parseHttpMethod(request: BufferedSource): String? {

147

return when (request.select(httpMethods)) {

148

0 -> "GET"

149

1 -> "POST"

150

2 -> "PUT"

151

3 -> "DELETE"

152

4 -> "PATCH"

153

else -> null // No match found

154

}

155

}

156

157

// Usage

158

val requestBuffer = Buffer().writeUtf8("POST /api/users HTTP/1.1\r\n")

159

val method = parseHttpMethod(requestBuffer)

160

println("HTTP Method: $method")

161

162

// Typed options for enum-like behavior

163

enum class ResponseCode(val code: String) {

164

OK("200 OK"),

165

NOT_FOUND("404 Not Found"),

166

SERVER_ERROR("500 Internal Server Error")

167

}

168

169

val responseOptions = TypedOptions.of(

170

ResponseCode.values().asIterable()

171

) { code -> code.code.encodeUtf8() }

172

173

fun parseResponseCode(response: BufferedSource): ResponseCode? {

174

return response.select(responseOptions)

175

}

176

177

// Usage

178

val responseBuffer = Buffer().writeUtf8("404 Not Found\r\n")

179

val responseCode = parseResponseCode(responseBuffer)

180

println("Response Code: $responseCode")

181

```

182

183

### Protocol Parsing Example

184

185

```kotlin

186

// Parse different message types in a protocol

187

sealed class Message

188

object PingMessage : Message()

189

data class DataMessage(val payload: String) : Message()

190

data class ErrorMessage(val error: String) : Message()

191

192

val messageTypes = Options.of(

193

"PING".encodeUtf8(),

194

"DATA".encodeUtf8(),

195

"ERROR".encodeUtf8()

196

)

197

198

fun parseMessage(source: BufferedSource): Message? {

199

return when (source.select(messageTypes)) {

200

0 -> {

201

source.readUtf8Line() // Consume rest of line

202

PingMessage

203

}

204

1 -> {

205

val length = source.readUtf8Line()?.toIntOrNull() ?: return null

206

val payload = source.readUtf8(length.toLong())

207

DataMessage(payload)

208

}

209

2 -> {

210

val error = source.readUtf8Line() ?: return null

211

ErrorMessage(error)

212

}

213

else -> null

214

}

215

}

216

217

// Test protocol parsing

218

val protocolBuffer = Buffer()

219

.writeUtf8("DATA\n")

220

.writeUtf8("12\n")

221

.writeUtf8("Hello, World")

222

223

val message = parseMessage(protocolBuffer)

224

println("Parsed message: $message")

225

```

226

227

## Advanced Buffer Operations

228

229

### UnsafeCursor for High-Performance Access

230

231

The UnsafeCursor provides low-level access to Buffer's internal segments for high-performance operations.

232

233

```kotlin { .api }

234

class Buffer.UnsafeCursor {

235

var buffer: Buffer?

236

var readWrite: Boolean

237

var offset: Long

238

var data: ByteArray?

239

var start: Int

240

var end: Int

241

242

fun next(): Int

243

fun seek(offset: Long): Int

244

fun resizeBuffer(newSize: Long): Long

245

fun expandBuffer(minByteCount: Int): Long

246

}

247

248

expect class Buffer {

249

fun readUnsafe(unsafeCursor: UnsafeCursor = UnsafeCursor()): UnsafeCursor

250

fun readAndWriteUnsafe(unsafeCursor: UnsafeCursor = UnsafeCursor()): UnsafeCursor

251

}

252

```

253

254

### UnsafeCursor Usage Examples

255

256

```kotlin

257

// High-performance byte array search

258

fun findBytePattern(buffer: Buffer, pattern: ByteArray): Long {

259

var position = -1L

260

261

buffer.readUnsafe().use { cursor ->

262

cursor.seek(0L)

263

264

while (cursor.next() != -1) {

265

val segment = cursor.data ?: continue

266

267

// Search within current segment

268

for (i in cursor.start until cursor.end - pattern.size + 1) {

269

var match = true

270

for (j in pattern.indices) {

271

if (segment[i + j] != pattern[j]) {

272

match = false

273

break

274

}

275

}

276

if (match) {

277

position = cursor.offset + (i - cursor.start)

278

return position

279

}

280

}

281

}

282

}

283

284

return position

285

}

286

287

// Efficient byte manipulation

288

fun xorBuffer(buffer: Buffer, key: ByteArray) {

289

buffer.readAndWriteUnsafe().use { cursor ->

290

cursor.seek(0L)

291

var keyIndex = 0

292

293

while (cursor.next() != -1) {

294

val segment = cursor.data ?: continue

295

296

for (i in cursor.start until cursor.end) {

297

segment[i] = (segment[i].toInt() xor key[keyIndex % key.size].toInt()).toByte()

298

keyIndex++

299

}

300

}

301

}

302

}

303

304

// Usage

305

val buffer = Buffer().writeUtf8("Hello, Okio UnsafeCursor!")

306

val pattern = "Okio".encodeUtf8().toByteArray()

307

val position = findBytePattern(buffer, pattern)

308

println("Pattern found at position: $position")

309

310

// XOR encryption/decryption

311

val key = "SECRET".toByteArray()

312

val originalText = buffer.copy().readUtf8()

313

xorBuffer(buffer, key)

314

val encrypted = buffer.copy().readUtf8()

315

xorBuffer(buffer, key) // XOR again to decrypt

316

val decrypted = buffer.readUtf8()

317

318

println("Original: $originalText")

319

println("Encrypted: ${encrypted.encodeUtf8().hex()}")

320

println("Decrypted: $decrypted")

321

```

322

323

## Utility Functions

324

325

### Resource Management

326

327

```kotlin { .api }

328

// Automatic resource cleanup

329

inline fun <T : Closeable?, R> T.use(block: (T) -> R): R

330

```

331

332

### Core I/O Utilities

333

334

```kotlin { .api }

335

// Source and Sink utilities

336

fun Source.buffer(): BufferedSource

337

fun Sink.buffer(): BufferedSink

338

fun blackholeSink(): Sink

339

```

340

341

### Usage Examples

342

343

```kotlin

344

// Safe resource handling

345

fun processFileWithCleanup(path: Path): String {

346

return FileSystem.SYSTEM.source(path).use { source ->

347

source.buffer().use { buffered ->

348

buffered.readUtf8()

349

}

350

}

351

}

352

353

// Blackhole sink for testing or discarding data

354

fun measureCompressionRatio(data: String): Double {

355

val originalSize = data.length

356

val compressedSize = Buffer()

357

358

blackholeSink().gzip().use { compressor ->

359

compressor.writeUtf8(data)

360

// Data is compressed but discarded

361

}

362

363

// In real scenario, you'd measure compressed size

364

return 0.5 // Placeholder

365

}

366

367

// Chaining buffer operations

368

fun transformData(input: String): String {

369

return Buffer()

370

.writeUtf8(input)

371

.let { buffer ->

372

// Transform to uppercase

373

val upperData = buffer.readUtf8().uppercase()

374

Buffer().writeUtf8(upperData)

375

}

376

.let { buffer ->

377

// Add prefix and suffix

378

buffer.writeUtf8(" [PROCESSED]")

379

"[DATA] ${buffer.readUtf8()}"

380

}

381

}

382

383

val result = transformData("hello world")

384

println(result) // [DATA] HELLO WORLD [PROCESSED]

385

```

386

387

## Platform-Specific Extensions

388

389

### Apple Platform Extensions (appleMain)

390

391

Okio provides specific extensions for Apple platforms to integrate with Foundation framework.

392

393

```kotlin { .api }

394

// Foundation NSData integration

395

fun NSData.toByteString(): ByteString

396

```

397

398

### Usage Examples

399

400

```kotlin

401

// Converting Foundation NSData to Okio ByteString (iOS/macOS)

402

import platform.Foundation.NSData

403

import platform.Foundation.NSString

404

import platform.Foundation.dataUsingEncoding

405

import platform.Foundation.NSUTF8StringEncoding

406

407

fun foundationIntegration() {

408

// Create NSData from NSString

409

val nsString = NSString.create(string = "Hello from Foundation!")

410

val nsData = nsString.dataUsingEncoding(NSUTF8StringEncoding) ?: return

411

412

// Convert to Okio ByteString

413

val byteString = nsData.toByteString()

414

415

println("NSData converted to ByteString: ${byteString.utf8()}")

416

println("ByteString hex: ${byteString.hex()}")

417

418

// Use with Okio operations

419

val hash = byteString.sha256()

420

println("SHA-256: ${hash.hex()}")

421

}

422

```

423

424

### Native Platform Features

425

426

On native platforms (including iOS), Okio provides optimized implementations:

427

428

- **Native zlib integration**: High-performance compression using system libraries

429

- **Memory-mapped file I/O**: Efficient file access for large files

430

- **POSIX-compliant file operations**: Full Unix file system support

431

432

## Threading and Concurrency

433

434

### Thread Safety Considerations

435

436

```kotlin { .api }

437

// Platform-specific lock implementation

438

expect class Lock() {

439

inline fun <T> withLock(action: () -> T): T

440

}

441

```

442

443

### Safe Concurrent Operations

444

445

```kotlin

446

// Thread-safe buffer operations

447

class ThreadSafeBuffer {

448

private val buffer = Buffer()

449

private val lock = Lock()

450

451

fun write(data: ByteString) {

452

lock.withLock {

453

buffer.write(data)

454

}

455

}

456

457

fun read(): ByteString? {

458

return lock.withLock {

459

if (buffer.size > 0) {

460

buffer.readByteString()

461

} else {

462

null

463

}

464

}

465

}

466

467

fun size(): Long {

468

return lock.withLock {

469

buffer.size

470

}

471

}

472

}

473

474

// Usage in multi-threaded environment

475

val safeBuffer = ThreadSafeBuffer()

476

477

// Thread 1: Writing data

478

Thread {

479

repeat(100) { i ->

480

safeBuffer.write("Message $i\n".encodeUtf8())

481

Thread.sleep(10)

482

}

483

}.start()

484

485

// Thread 2: Reading data

486

Thread {

487

repeat(50) {

488

val data = safeBuffer.read()

489

if (data != null) {

490

println("Read: ${data.utf8().trim()}")

491

}

492

Thread.sleep(20)

493

}

494

}.start()

495

```

496

497

## Error Handling Utilities

498

499

### Common Exception Types

500

501

```kotlin { .api }

502

// Platform-specific exception implementations

503

expect open class IOException : Exception

504

expect class EOFException : IOException

505

expect class FileNotFoundException : IOException

506

expect class ProtocolException : IOException

507

expect class ArrayIndexOutOfBoundsException : Exception

508

```

509

510

### Robust Error Handling Patterns

511

512

```kotlin

513

// Retry mechanism for I/O operations

514

fun <T> retryOperation(

515

maxAttempts: Int = 3,

516

delayMs: Long = 1000,

517

operation: () -> T

518

): T? {

519

repeat(maxAttempts) { attempt ->

520

try {

521

return operation()

522

} catch (e: IOException) {

523

println("Attempt ${attempt + 1} failed: ${e.message}")

524

if (attempt < maxAttempts - 1) {

525

Thread.sleep(delayMs)

526

}

527

}

528

}

529

return null

530

}

531

532

// Safe file operations with fallback

533

fun safeReadFile(path: Path, fallbackContent: String = ""): String {

534

return try {

535

FileSystem.SYSTEM.read(path) { readUtf8() }

536

} catch (e: FileNotFoundException) {

537

println("File not found, using fallback: $path")

538

fallbackContent

539

} catch (e: IOException) {

540

println("I/O error reading file: ${e.message}")

541

fallbackContent

542

}

543

}

544

545

// Graceful resource cleanup

546

fun <T : Closeable> safeClose(resource: T?) {

547

try {

548

resource?.close()

549

} catch (e: Exception) {

550

println("Error closing resource: ${e.message}")

551

}

552

}

553

554

// Usage

555

val result = retryOperation(maxAttempts = 3) {

556

FileSystem.SYSTEM.read("/tmp/unreliable-file.txt".toPath()) {

557

readUtf8()

558

}

559

}

560

561

if (result != null) {

562

println("Successfully read file: ${result.take(50)}...")

563

} else {

564

println("Failed to read file after retries")

565

}

566

```

567

568

## Performance Optimization Utilities

569

570

### Memory Pool Management

571

572

```kotlin

573

// Efficient buffer reuse

574

class BufferPool(private val maxSize: Int = 10) {

575

private val pool = mutableListOf<Buffer>()

576

private val lock = Lock()

577

578

fun acquire(): Buffer {

579

return lock.withLock {

580

if (pool.isNotEmpty()) {

581

pool.removeAt(pool.size - 1)

582

} else {

583

Buffer()

584

}

585

}

586

}

587

588

fun release(buffer: Buffer) {

589

lock.withLock {

590

if (pool.size < maxSize) {

591

buffer.clear()

592

pool.add(buffer)

593

}

594

}

595

}

596

597

inline fun <T> withBuffer(action: (Buffer) -> T): T {

598

val buffer = acquire()

599

try {

600

return action(buffer)

601

} finally {

602

release(buffer)

603

}

604

}

605

}

606

607

// Usage

608

val bufferPool = BufferPool()

609

610

// Efficient data processing without allocations

611

fun processData(data: List<String>): List<String> {

612

return data.map { input ->

613

bufferPool.withBuffer { buffer ->

614

buffer.writeUtf8(input.uppercase())

615

buffer.writeUtf8(" [PROCESSED]")

616

buffer.readUtf8()

617

}

618

}

619

}

620

```

621

622

### Batch Operations

623

624

```kotlin

625

// Efficient batch file processing

626

fun processBatchFiles(filePaths: List<Path>, processor: (String) -> String) {

627

val fs = FileSystem.SYSTEM

628

629

filePaths.chunked(10).forEach { batch ->

630

batch.forEach { path ->

631

try {

632

val content = fs.read(path) { readUtf8() }

633

val processed = processor(content)

634

635

val outputPath = path.parent!! / "${path.name}.processed"

636

fs.write(outputPath) { writeUtf8(processed) }

637

638

} catch (e: Exception) {

639

println("Error processing $path: ${e.message}")

640

}

641

}

642

643

// Small delay between batches to prevent resource exhaustion

644

Thread.sleep(100)

645

}

646

}

647

```

648

649

## Debugging and Inspection Utilities

650

651

### Buffer Content Inspection

652

653

```kotlin

654

// Debug buffer contents

655

fun debugBuffer(buffer: Buffer, name: String = "Buffer") {

656

println("=== $name Debug Info ===")

657

println("Size: ${buffer.size} bytes")

658

659

if (buffer.size > 0) {

660

val snapshot = buffer.snapshot()

661

println("Hex: ${snapshot.hex()}")

662

663

// Try to display as text if printable

664

val text = try {

665

snapshot.utf8()

666

} catch (e: Exception) {

667

"[Non-UTF8 data]"

668

}

669

670

println("Text: ${text.take(100)}${if (text.length > 100) "..." else ""}")

671

}

672

println("========================")

673

}

674

675

// Trace I/O operations

676

class TracingSource(private val delegate: Source, private val name: String) : Source by delegate {

677

override fun read(sink: Buffer, byteCount: Long): Long {

678

val bytesRead = delegate.read(sink, byteCount)

679

println("$name: Read $bytesRead bytes (requested $byteCount)")

680

return bytesRead

681

}

682

}

683

684

class TracingSink(private val delegate: Sink, private val name: String) : Sink by delegate {

685

override fun write(source: Buffer, byteCount: Long) {

686

println("$name: Writing $byteCount bytes")

687

delegate.write(source, byteCount)

688

}

689

}

690

691

// Usage

692

val buffer = Buffer().writeUtf8("Hello, debugging!")

693

debugBuffer(buffer, "Test Buffer")

694

695

val tracingSource = TracingSource(buffer, "Debug Source")

696

val output = Buffer()

697

tracingSource.read(output, 5) // Will print tracing info

698

```