use core::ffi::c_int;
use crate::error::{Error, ErrorCategory, Result};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
#[repr(transparent)]
pub struct ColumnIndex(c_int);
impl ColumnIndex {
pub const INITIAL: Self = Self(0);
pub const fn new(value: c_int) -> Self {
Self(value)
}
#[inline]
pub const fn value(&self) -> c_int {
self.0
}
pub const fn next(&self) -> Self {
Self(self.value() + 1)
}
}
impl From<ColumnIndex> for i32 {
fn from(index: ColumnIndex) -> Self {
index.value() as Self
}
}
impl From<ColumnIndex> for u32 {
fn from(index: ColumnIndex) -> Self {
index.value() as Self
}
}
impl From<ColumnIndex> for i64 {
fn from(index: ColumnIndex) -> Self {
index.value() as Self
}
}
impl From<ColumnIndex> for u64 {
fn from(index: ColumnIndex) -> Self {
index.value() as Self
}
}
impl From<ColumnIndex> for isize {
fn from(index: ColumnIndex) -> Self {
index.value() as Self
}
}
impl From<ColumnIndex> for usize {
fn from(index: ColumnIndex) -> Self {
index.value() as Self
}
}
impl TryFrom<i32> for ColumnIndex {
type Error = Error;
fn try_from(value: i32) -> Result<Self> {
if value >= 0 {
Ok(Self::new(value as c_int))
} else {
Err(invalid_index())
}
}
}
impl TryFrom<i64> for ColumnIndex {
type Error = Error;
fn try_from(value: i64) -> Result<Self> {
match c_int::try_from(value) {
Ok(value) if value >= 0 => Ok(Self::new(value)),
_ => Err(invalid_index()),
}
}
}
impl TryFrom<isize> for ColumnIndex {
type Error = Error;
fn try_from(value: isize) -> Result<Self> {
match c_int::try_from(value) {
Ok(value) if value >= 0 => Ok(Self::new(value)),
_ => Err(invalid_index()),
}
}
}
impl TryFrom<u32> for ColumnIndex {
type Error = Error;
fn try_from(value: u32) -> Result<Self> {
match c_int::try_from(value) {
Ok(value) => Ok(Self::new(value)),
Err(_) => Err(invalid_index()),
}
}
}
impl TryFrom<u64> for ColumnIndex {
type Error = Error;
fn try_from(value: u64) -> Result<Self> {
match c_int::try_from(value) {
Ok(value) => Ok(Self::new(value)),
Err(_) => Err(invalid_index()),
}
}
}
impl TryFrom<usize> for ColumnIndex {
type Error = Error;
fn try_from(value: usize) -> Result<Self> {
match c_int::try_from(value) {
Ok(value) => Ok(Self::new(value)),
Err(_) => Err(invalid_index()),
}
}
}
#[cold]
fn invalid_index() -> Error {
ErrorCategory::Range.into()
}
#[cfg(all(nightly, feature = "lang-step-trait"))]
impl core::iter::Step for ColumnIndex {
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
if start.0 <= end.0 {
let steps = (end.0 - start.0) as usize;
(steps, Some(steps))
} else {
(0, None)
}
}
fn forward_checked(start: Self, count: usize) -> Option<Self> {
let count = c_int::try_from(count).ok()?;
let new_value = start.0.checked_add(count)?;
Some(Self(new_value))
}
fn backward_checked(start: Self, count: usize) -> Option<Self> {
let count = c_int::try_from(count).ok()?;
let new_value = start.0.checked_sub(count)?;
Some(Self(new_value))
}
}