#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::ops::{Add, AddAssign, Sub, SubAssign};
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BytePos(pub usize);
impl BytePos {
pub fn shift(self, ch: char) -> Self {
BytePos(self.0 + ch.len_utf8())
}
}
impl From<usize> for BytePos {
fn from(value: usize) -> Self {
BytePos(value)
}
}
impl From<BytePos> for usize {
fn from(value: BytePos) -> Self {
value.0
}
}
impl Add<BytePos> for BytePos {
type Output = Self;
fn add(self, rhs: BytePos) -> Self::Output {
BytePos(self.0 + rhs.0)
}
}
impl Add<usize> for BytePos {
type Output = Self;
fn add(self, rhs: usize) -> Self::Output {
BytePos(self.0 + rhs)
}
}
impl AddAssign<usize> for BytePos {
fn add_assign(&mut self, rhs: usize) {
self.0 += rhs;
}
}
impl AddAssign<BytePos> for BytePos {
fn add_assign(&mut self, rhs: BytePos) {
self.0 += rhs.0;
}
}
impl Sub<BytePos> for BytePos {
type Output = Self;
fn sub(self, rhs: BytePos) -> Self::Output {
BytePos(self.0 - rhs.0)
}
}
impl Sub<usize> for BytePos {
type Output = Self;
fn sub(self, rhs: usize) -> Self::Output {
BytePos(self.0 - rhs)
}
}
impl SubAssign<usize> for BytePos {
fn sub_assign(&mut self, rhs: usize) {
self.0 -= rhs;
}
}
impl SubAssign<BytePos> for BytePos {
fn sub_assign(&mut self, rhs: BytePos) {
self.0 -= rhs.0;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_addition_operations() {
let mut pos = BytePos(5);
assert_eq!(pos + 3, BytePos(8));
pos += 3;
assert_eq!(pos, BytePos(8));
}
#[test]
fn test_subtraction_operations() {
let mut pos = BytePos(5);
assert_eq!(pos - 3, BytePos(2));
pos -= 3;
assert_eq!(pos, BytePos(2));
}
#[test]
fn test_shift_with_different_chars() {
let pos = BytePos(0);
assert_eq!(pos.shift('a'), BytePos(1));
assert_eq!(pos.shift('é'), BytePos(2));
assert_eq!(pos.shift('€'), BytePos(3));
assert_eq!(pos.shift('🦀'), BytePos(4));
let pos2 = BytePos(0);
let final_pos = pos2.shift('a').shift('€').shift('🦀');
assert_eq!(final_pos, BytePos(8)); }
}