#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ProgramSource<'source> {
bytes: &'source [u8],
}
impl<'source> ProgramSource<'source> {
#[must_use]
pub const fn from_bytes(bytes: &'source [u8]) -> Self {
Self { bytes }
}
#[must_use]
pub const fn from_str(source: &'source str) -> Self {
Self {
bytes: source.as_bytes(),
}
}
#[must_use]
pub const fn as_bytes(self) -> &'source [u8] {
self.bytes
}
#[must_use]
pub const fn is_empty(self) -> bool {
self.bytes.is_empty()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceLineNumber {
one_based: usize,
}
impl SourceLineNumber {
pub(crate) const MAX: Self = Self {
one_based: usize::MAX,
};
#[cfg(test)]
pub(crate) fn from_one_based(one_based: usize) -> Option<Self> {
(one_based != 0).then_some(Self { one_based })
}
pub(crate) fn from_zero_based(zero_based: usize) -> Option<Self> {
let one_based = zero_based.checked_add(1)?;
Some(Self { one_based })
}
#[must_use]
pub const fn get(self) -> usize {
self.one_based
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceColumn {
one_based: usize,
}
impl SourceColumn {
pub(crate) fn from_zero_based(zero_based: usize) -> Option<Self> {
let one_based = zero_based.checked_add(1)?;
Some(Self { one_based })
}
#[cfg(test)]
pub(crate) fn from_one_based(one_based: usize) -> Option<Self> {
(one_based != 0).then_some(Self { one_based })
}
#[must_use]
pub const fn get(self) -> usize {
self.one_based
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourcePosition {
line: SourceLineNumber,
column: SourceColumn,
}
impl SourcePosition {
pub(crate) const fn new(line: SourceLineNumber, column: SourceColumn) -> Self {
Self { line, column }
}
#[must_use]
pub const fn line(self) -> SourceLineNumber {
self.line
}
#[must_use]
pub const fn column(self) -> SourceColumn {
self.column
}
}