use crate::lazy::binary::raw::v1_1::binary_buffer::BinaryBuffer;
use crate::lazy::streaming_raw_reader::IoBuffer;
use crate::lazy::text::buffer::TextBuffer;
use crate::result::IonFailure;
use crate::{HasRange, IonError, IonResult};
use std::ops::Range;
#[derive(Debug, Copy, Clone)]
pub struct Span<'a> {
bytes: &'a [u8],
offset: usize,
}
impl AsRef<[u8]> for Span<'_> {
fn as_ref(&self) -> &[u8] {
self.bytes()
}
}
impl<'a> From<Span<'a>> for &'a [u8] {
fn from(value: Span<'a>) -> Self {
value.bytes
}
}
impl<A: AsRef<[u8]>> PartialEq<A> for Span<'_> {
fn eq(&self, other: &A) -> bool {
self.bytes() == other.as_ref()
}
}
impl<'a> Span<'a> {
pub fn with_offset(offset: usize, bytes: &'a [u8]) -> Self {
Self { bytes, offset }
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn range(&self) -> Range<usize> {
self.offset..self.offset + self.bytes.len()
}
pub fn bytes(&self) -> &'a [u8] {
self.bytes
}
pub fn text(&self) -> Option<&'a str> {
self.expect_text().ok()
}
pub fn expect_text(&self) -> IonResult<&'a str> {
std::str::from_utf8(self.bytes)
.map_err(|_| IonError::decoding_error("span text was not valid UTF-8"))
}
pub fn len(&self) -> usize {
self.bytes.len()
}
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
pub fn slice(&self, offset: usize, length: usize) -> Span<'a> {
Self {
bytes: &self.bytes[offset..offset + length],
offset: self.offset + offset,
}
}
pub fn slice_to_end(&self, offset: usize) -> Span<'a> {
Self {
bytes: &self.bytes[offset..],
offset: self.offset + offset,
}
}
}
impl HasRange for Span<'_> {
fn range(&self) -> Range<usize> {
self.offset..self.offset + self.bytes.len()
}
}
impl<'a> From<BinaryBuffer<'a>> for Span<'a> {
fn from(value: BinaryBuffer<'a>) -> Self {
Span {
bytes: value.bytes(),
offset: value.offset(),
}
}
}
impl<'a> From<TextBuffer<'a>> for Span<'a> {
fn from(value: TextBuffer<'a>) -> Self {
Span {
bytes: value.bytes(),
offset: value.offset(),
}
}
}
impl<'a> From<&'a IoBuffer> for Span<'a> {
fn from(value: &'a IoBuffer) -> Self {
Span {
bytes: value.remaining_bytes(),
offset: value.stream_position(),
}
}
}