skan 0.1.0

Skan is a Rust-native, Java Scanner-inspired library that provides type-safe, convenient methods for parsing various data types from multiple input sources with robust error handling and comprehensive documentation.
Documentation
# Skan

`skan` is a small Rust crate that provides functionality similar to Java's `Scanner` class. It allows reading input from various sources (strings, files, etc.) and parsing them into different types, such as words, lines, integers, and floats.

---

## Features

- Create a scanner from a string or any type implementing `Read`.
- Read input byte-by-byte, word-by-word, or line-by-line.
- Parse numbers (integers, floats, doubles) with error handling.
- Iterator support for byte-wise reading.
- Custom errors for parsing and end-of-data scenarios.

---

## Installation

You can install `skan` either from Crates.io or directly from the Git repository.

### Installing from Crates.io

1. Open your `Cargo.toml` file.
2. Add `skan` to your dependencies:

```toml
[dependencies]
skan = "0.1.0"
```

3. In your Rust code, import the scanner:

```rust
use skan::scanner::Scanner;
```

4. Create a `Scanner` instance to read input:

```rust
let mut sc = Scanner::from_str("Hello world");
let word = sc.next_word();
```
### Installing directly from Git

1. Open your `Cargo.toml` file.
2. Add `skan` as a dependency using the Git repository URL:

```toml
[dependencies]
skan = { git = "https://github.com/2teez/skan" }
```

3. Import and use the crate as usual:

```rust
use skan::scanner::Scanner;
let mut sc = Scanner::from_str("Hello world");
let word = sc.next_word();
```

---

## Modules

### `scanner`

This module contains the main `Scanner` struct and related functionality.

#### `ScannerError<E>`

An enum representing possible scanner errors:

- `NoMoreData` – when there are no more items to read.
- `ParseError(E)` – when parsing a string into a number fails.

Implements `Display` and `Error` traits for descriptive error messages.

#### `Scanner` struct

Holds the scanner state:

- `data: Vec<u8>` – the raw input bytes.
- `wrds: Option<Vec<String>>` – optional cached split words/lines.
- `counter: usize` – current reading position.

---

## Creating a Scanner

#### From a reader:

```rust
use skan::scanner::Scanner;
use std::fs::File;

let file = File::open("input.txt").unwrap();
let mut scanner = Scanner::new(file);
```

#### From a string:

```rust
let mut scanner = Scanner::from_str("Hello World");
```

---

## Methods

#### `has_next() -> bool`

Checks if there is more data to read.

```rust
let scanner = Scanner::from_str("Got it.");
assert!(scanner.has_next());
```

---

#### `next_byte() -> Option<u8>`

Returns the next byte from the input without advancing the counter if there is data.

```rust
let scanner = Scanner::from_str("Hot it.");
assert_eq!(scanner.next_byte(), Some(72)); // 'H'
```

---

#### `next_word() -> Option<String>`

Returns the next word (split by space) from the input.

```rust
let mut scanner = Scanner::from_str("Hot it.");
scanner.next_word();
scanner.next_word();
assert_eq!(scanner.next_word(), None);
```

---

#### `next_line() -> Option<String>`

Returns the next line (split by `\n`) from the input.

```rust
let mut scanner = Scanner::from_str("Hot it.\nGot it.");
scanner.next_line();
assert_eq!(scanner.next_line(), Some("Got it.".to_string()));
```

---

#### `next_number<T>() -> Result<T, ScannerError<T::Err>>`

Parses the next word as a number of type `T`.

```rust
let mut scanner = Scanner::from_str("from 23 to 45");
scanner.next_word();
scanner.next_word();
scanner.next_word();
assert_eq!(scanner.next_number::<u32>().unwrap(), 45);
```

---

#### `next_int<T>() -> Result<T, ScannerError<T::Err>>`

Parses the next word as an integer. Requires `T` to implement the `Int` trait.

```rust
use skan::numbers::Int;
let mut scanner = Scanner::from_str("from 47 until 100");
scanner.next_word();
scanner.next_word();
scanner.next_word();
assert_eq!(scanner.next_int::<i32>().unwrap(), 100);
```

---

#### `next_float<T>() -> Result<T, ScannerError<T::Err>>`

Parses the next word as a floating-point number. Requires `T` to implement the `Float` trait.

```rust
use skan::numbers::Float;
let mut scanner = Scanner::from_str("from 3.194");
scanner.next_word();
assert_eq!(scanner.next_float::<f32>().unwrap(), 3.194);
```

---

#### `next_double() -> Result<f64, ScannerError<f64::Err>>`

Parses the next word as an `f64` floating-point number.

```rust
let mut scanner = Scanner::from_str("6.9669987654230");
assert_eq!(scanner.next_double().unwrap(), 6.9669987654230);
```

---

#### `Iterator` Implementation

`Scanner` implements `Iterator<Item = u8>` to read input byte-by-byte.

```rust
let mut scanner = Scanner::from_str("Hello");
for byte in &mut scanner {
    println!("{}", byte); // prints ASCII values
}
```

---

### Internal Helper Methods

- `delimiter(&self, sep: char) -> Vec<String>` – splits the input by the given separator (`' '` or `'\n'`) and returns non-empty strings.

---

## Example Usage

```rust
use skan::scanner::Scanner;
use skan::numbers::{Int, Float};

let mut scanner = Scanner::from_str("Age 30, Score 95.5");

scanner.next_word(); // skip "Age"
let age: i32 = scanner.next_int().unwrap();

scanner.next_word(); // skip "Score"
let score: f32 = scanner.next_float().unwrap();

println!("Age: {}, Score: {}", age, score);
```

---

## Error Handling

`ScannerError` helps identify when parsing fails or when there is no more data. Always handle `Result` when calling number parsing methods:

```rust
match scanner.next_int::<i32>() {
    Ok(value) => println!("Next int: {}", value),
    Err(e) => eprintln!("Error: {}", e),
}
```

---