use crate::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Anchor {
inner: InnerAnchor,
bias: AnchorBias,
}
impl Anchor {
#[inline(always)]
pub(crate) fn bias(&self) -> AnchorBias {
self.bias
}
#[inline(always)]
pub(crate) fn end_of_document() -> Self {
Self::new(InnerAnchor::zero(), AnchorBias::Right)
}
#[inline(always)]
pub(crate) fn inner(&self) -> InnerAnchor {
self.inner
}
#[inline(always)]
pub(crate) fn is_end_of_document(&self) -> bool {
self.inner.is_zero() && self.bias == AnchorBias::Right
}
#[inline(always)]
pub(crate) fn is_start_of_document(&self) -> bool {
self.inner.is_zero() && self.bias == AnchorBias::Left
}
#[inline(always)]
pub(crate) fn new(inner: InnerAnchor, bias: AnchorBias) -> Self {
Self { inner, bias }
}
#[inline(always)]
pub(crate) fn start_of_document() -> Self {
Self::new(InnerAnchor::zero(), AnchorBias::Left)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum AnchorBias {
Left,
Right,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub(crate) struct InnerAnchor {
replica_id: ReplicaId,
contained_in: RunTs,
offset: Length,
}
impl core::fmt::Debug for InnerAnchor {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
if self == &Self::zero() {
write!(f, "zero")
} else if f.alternate() {
write!(
f,
"{:x}.{} in {}",
self.replica_id, self.offset, self.contained_in
)
} else {
write!(f, "{:x}.{}", self.replica_id, self.offset)
}
}
}
impl InnerAnchor {
#[inline(always)]
pub(crate) fn is_zero(&self) -> bool {
self.replica_id == 0
}
#[inline(always)]
pub(crate) fn new(
replica_id: ReplicaId,
offset: Length,
run_ts: RunTs,
) -> Self {
Self { replica_id, offset, contained_in: run_ts }
}
#[inline(always)]
pub(crate) fn offset(&self) -> Length {
self.offset
}
#[inline(always)]
pub(crate) fn replica_id(&self) -> ReplicaId {
self.replica_id
}
#[inline(always)]
pub(crate) fn run_ts(&self) -> RunTs {
self.contained_in
}
#[inline]
pub const fn zero() -> Self {
Self { replica_id: 0, offset: 0, contained_in: 0 }
}
}
#[cfg(feature = "encode")]
mod encode {
use super::*;
use crate::encode::{BoolDecodeError, Decode, Encode, IntDecodeError};
impl Encode for Anchor {
#[inline]
fn encode(&self, buf: &mut Vec<u8>) {
self.inner.encode(buf);
self.bias.encode(buf);
}
}
pub(crate) enum AnchorDecodeError {
Bool(BoolDecodeError),
Int(IntDecodeError),
}
impl From<BoolDecodeError> for AnchorDecodeError {
#[inline(always)]
fn from(err: BoolDecodeError) -> Self {
Self::Bool(err)
}
}
impl From<IntDecodeError> for AnchorDecodeError {
#[inline(always)]
fn from(err: IntDecodeError) -> Self {
Self::Int(err)
}
}
impl core::fmt::Display for AnchorDecodeError {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
let err: &dyn core::fmt::Display = match self {
Self::Bool(err) => err,
Self::Int(err) => err,
};
write!(f, "Anchor couldn't be decoded: {}", err)
}
}
impl Decode for Anchor {
type Value = Self;
type Error = AnchorDecodeError;
#[inline]
fn decode(buf: &[u8]) -> Result<(Self, &[u8]), Self::Error> {
let (inner, buf) = InnerAnchor::decode(buf)?;
let (bias, buf) = AnchorBias::decode(buf)?;
let anchor = Self::new(inner, bias);
Ok((anchor, buf))
}
}
impl Encode for InnerAnchor {
#[inline]
fn encode(&self, buf: &mut Vec<u8>) {
self.replica_id().encode(buf);
self.run_ts().encode(buf);
self.offset().encode(buf);
}
}
impl Decode for InnerAnchor {
type Value = Self;
type Error = IntDecodeError;
#[inline]
fn decode(buf: &[u8]) -> Result<(Self, &[u8]), Self::Error> {
let (replica_id, buf) = ReplicaId::decode(buf)?;
let (run_ts, buf) = RunTs::decode(buf)?;
let (offset, buf) = Length::decode(buf)?;
let anchor = Self::new(replica_id, offset, run_ts);
Ok((anchor, buf))
}
}
impl Encode for AnchorBias {
#[inline]
fn encode(&self, buf: &mut Vec<u8>) {
matches!(self, Self::Right).encode(buf);
}
}
impl Decode for AnchorBias {
type Value = Self;
type Error = BoolDecodeError;
#[inline]
fn decode(buf: &[u8]) -> Result<(Self, &[u8]), Self::Error> {
let (is_right, buf) = bool::decode(buf)?;
let bias = if is_right { Self::Right } else { Self::Left };
Ok((bias, buf))
}
}
}
#[cfg(feature = "serde")]
mod serde {
crate::encode::impl_serialize!(super::Anchor);
crate::encode::impl_deserialize!(super::Anchor);
}