# span
[English README](README_en.md)
Apache-2.0 许可证
一个用于处理**闭开区间**与**闭无限区间**的 Rust 轻量库,核心提供 `Span<T>` 泛型枚举类型,标准化管理有限/无限区间,支持区间包含判断、大小计算、迭代等核心能力,且完全适配 Rust 原生区间类型(`Range`/`RangeFrom`)。
> 本库仅依赖 `num-traits`(数值能力扩展)和 `thiserror`(错误处理),无其他冗余依赖,可无缝集成到各类 Rust 项目中。
## 主要特性
- 双区间类型支持:同时兼容**有限闭开区间**(`[start, end)`)与**无限闭区间**(`[start, +∞)`)
- 完善的区间判断:支持元素归属判断、空区间判断、区间包含关系判断(A区间是否完全包含B区间)
- 便捷的元信息获取:快速获取起始/结束值、区分有限/无限区间类型、转换原生区间类型
- 实用数值计算:支持有限区间的大小计算,空区间/无限区间返回明确的结果/错误
- 原生 Trait 适配:实现 `From`(兼容 Rust 原生 `Range`/`RangeFrom`)、`Default`、`Iterator`、`Display` 等核心 Trait
- 泛型兼容:适配所有满足 `PartialOrd`/`Copy`/`Sub` 等基础约束的数值类型(如 `u8`/`u32`/`i64` 等)
## 适用场景
- 标准化管理数值区间(如分块存储、数据分片、索引范围界定)
- 需区分有限/无限区间并统一处理(如资源分配、任务调度的范围定义)
- 需对区间进行迭代、包含判断、大小计算的场景(如算法优化、数据校验)
## 快速开始
### 添加依赖
在 `Cargo.toml` 中引入本库:
```toml
[dependencies]
span = "0.1.0" # 替换为实际版本号
num-traits = "0.2"
thiserror = "1.0"
```
### 核心使用示例
```rust
use span::Span;
use std::ops::{Range, RangeFrom};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 创建区间(支持原生Range/RangeFrom转换)
let finite_span: Span<u32> = (3..5).into(); // 有限闭开区间 [3,5)
let infinite_span: Span<u32> = (3..).into(); // 无限闭区间 [3, +∞)
// 直接构造
let finite_span2 = Span::new_finite(2, 7);
let infinite_span2 = Span::new_infinite(5);
// 2. 元素包含判断
assert!(finite_span2.contains(&3));
assert!(!finite_span2.contains(&7));
assert!(infinite_span2.contains(&10));
assert!(!infinite_span2.contains(&3));
// 3. 空区间判断
assert!(Span::new_finite(5, 3).is_empty()); // start >= end 视为空
assert!(!finite_span.is_empty());
assert!(!infinite_span.is_empty());
// 4. 区间包含关系判断
let parent_span = Span::new_finite(1, 10);
let child_span = Span::new_finite(2, 5);
assert!(parent_span.contains_span(&child_span));
assert!(!child_span.contains_span(&parent_span));
// 5. 区间大小计算
assert_eq!(finite_span.size()?, Some(2)); // 5-3=2
assert!(Span::new_finite(5, 3).size().is_err()); // 空区间返回错误
assert_eq!(infinite_span.size()?, None); // 无限区间返回None
// 6. 区间迭代(有限区间迭代终止,无限区间永不停止)
let mut iter_span = Span::new_finite(1, 4);
assert_eq!(iter_span.next(), Some(1));
assert_eq!(iter_span.next(), Some(2));
assert_eq!(iter_span.next(), Some(3));
assert_eq!(iter_span.next(), None); // 有限区间迭代结束
// 7. 元信息获取
assert_eq!(finite_span.start(), &3);
assert_eq!(finite_span.end(), Some(&5));
assert_eq!(infinite_span.end(), None);
assert!(finite_span.is_finite());
assert!(infinite_span.is_infinite());
// 8. 格式化输出
println!("有限区间:{}", finite_span); // 输出 [3, 5)
println!("无限区间:{}", infinite_span); // 输出 [3, +∞)
Ok(())
}
```
## 主要 API 概览
### 核心枚举:`Span<T>`
| `Finite(Range<T>)` | 有限闭开区间 `[start, end)` |
| `Infinite(RangeFrom<T>)` | 无限闭区间 `[start, +∞)` |
### 基础构造/转换方法
| `Span::new_finite(start: T, end: T)` | 构造有限区间 |
| `Span::new_infinite(start: T)` | 构造无限区间 |
| `Span::from_finite(range: Range<T>)` | 从原生 `Range` 转换 |
| `Span::from_infinite(range: RangeFrom<T>)` | 从原生 `RangeFrom` 转换 |
| `From<Range<T>> for Span<T>` | 原生 `Range` 隐式转换 |
| `From<RangeFrom<T>> for Span<T>` | 原生 `RangeFrom` 隐式转换 |
### 元信息获取方法
| `start(&self) -> &T` | 获取区间起始值 |
| `end(&self) -> Option<&T>` | 有限区间返回结束值,无限区间返回 `None` |
| `as_finite(&self) -> Option<&Range<T>>` | 转换为有限区间引用(非有限则返回 `None`) |
| `as_infinite(&self) -> Option<&RangeFrom<T>>` | 转换为无限区间引用(非无限则返回 `None`) |
| `is_finite(&self) -> bool` | 判断是否为有限区间 |
| `is_infinite(&self) -> bool` | 判断是否为无限区间 |
### 判断类方法(`T: PartialOrd`)
| `contains<U>(&self, item: &U) -> bool` | 判断元素是否包含在区间内 |
| `is_empty(&self) -> bool` | 判断是否为空区间(仅有限区间可能为空) |
| `contains_span(&self, other: &Self) -> bool` | 判断当前区间是否完全包含另一个区间 |
### 计算类方法(`T: Sub + Copy + PartialOrd`)
| `size(&self) -> Result<Option<O>, SpanError>` | 有限非空区间返回大小,空区间返回 `EmptyFiniteSpan` 错误,无限区间返回 `None` |
### Trait 实现
| `Default` | 默认返回 `T::default()..`(无限区间) |
| `Iterator` | 有限区间迭代至结束值,无限区间持续迭代(`T: One + CheckedAdd + PartialOrd + Copy`) |
| `Display` | 格式化输出(有限区间 `[start, end)`,无限区间 `[start, +∞)`) |
| `Clone/PartialEq/Eq/Hash/Debug` | 基础数据特性支持 |
## 设计与注意事项
1. **空区间定义**:仅有限区间可能为空(`start >= end` 时判定为空),无限区间永远非空;
2. **迭代行为**:有限区间迭代从 `start` 到 `end-1` 终止,无限区间会持续生成下一个值(需手动终止,避免死循环);
3. **泛型约束**:不同方法对泛型 `T` 有不同约束(如 `size` 需 `Sub`,`Iterator` 需 `CheckedAdd + One`),使用时需满足对应约束;
4. **错误处理**:区间大小计算通过 `SpanError::EmptyFiniteSpan` 明确标识空区间错误,便于调用方处理;
5. **类型安全**:通过枚举严格区分有限/无限区间,避免混用导致的逻辑错误。
## 示例与调试
仓库源码包含完整的注释与示例,重点关注:
- `Span::contains_span` 的区间包含逻辑(有限/无限区间的不同判断规则);
- `Iterator` 实现的迭代逻辑(有限区间终止条件、无限区间持续迭代);
- `size` 方法的错误处理(空区间的错误返回、无限区间的 `None` 返回)。
## TODO / 未来规划
- 新增区间交集、并集、差集计算能力;
- 支持区间截断、偏移等操作;
- 补充更多数值类型的测试用例(如 `i8`/`f64` 等);
- 完善多语言文档与使用示例。
## 贡献
欢迎提交 PR 与 Issue。
## 联系
详见仓库所有者主页 [Milk-COCO](https://github.com/Milk-COCO/)