rsdns 0.23.0

DNS Client Library
Documentation
use crate::{Error, Result};

#[derive(Clone, Debug)]
pub struct Cursor<'a> {
    buf: &'a [u8],
    pos: usize,
    orig: Option<&'a [u8]>,
}

impl<'s, 'a: 's> Cursor<'a> {
    #[inline]
    pub const fn new(buf: &'a [u8]) -> Cursor<'a> {
        Cursor {
            buf,
            pos: 0,
            orig: None,
        }
    }

    #[inline]
    pub const fn with_pos(buf: &'a [u8], pos: usize) -> Cursor<'a> {
        Cursor {
            buf,
            pos,
            orig: None,
        }
    }

    #[inline]
    pub fn clone_with_pos(&'s self, pos: usize) -> Cursor<'a> {
        Cursor {
            buf: self.buf,
            pos,
            orig: None,
        }
    }

    pub fn window(&mut self, size: usize) -> Result<()> {
        if self.orig.is_none() {
            if self.len() >= size {
                self.orig = Some(self.buf);
                self.buf = unsafe { self.buf.get_unchecked(..self.pos + size) };
                Ok(())
            } else {
                Err(Error::EndOfBuffer)
            }
        } else {
            Err(Error::CursorAlreadyInWindow)
        }
    }

    pub fn close_window(&mut self) -> Result<()> {
        if self.orig.is_some() {
            if self.pos == self.buf.len() {
                self.buf = self.orig.take().unwrap();
                Ok(())
            } else {
                Err(Error::CursorWindowError {
                    window_end: self.buf.len(),
                    pos: self.pos,
                })
            }
        } else {
            Err(Error::CursorNotInWindow)
        }
    }

    #[inline]
    pub fn pos(&self) -> usize {
        self.pos
    }

    #[inline]
    pub fn set_pos(&mut self, pos: usize) {
        self.pos = pos
    }

    pub fn skip(&mut self, distance: usize) -> Result<()> {
        if self.len() >= distance {
            self.pos += distance;
            Ok(())
        } else {
            Err(self.bound_error())
        }
    }

    pub fn len(&self) -> usize {
        let capacity = self.capacity();
        capacity.saturating_sub(self.pos)
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.buf.len()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn u16_be(&mut self) -> Result<u16> {
        r_be!(self, u16)
    }

    pub unsafe fn u16_be_unchecked(&mut self) -> u16 {
        ru_be!(self, u16)
    }

    pub fn u32_be(&mut self) -> Result<u32> {
        r_be!(self, u32)
    }

    pub fn u128_be(&mut self) -> Result<u128> {
        r_be!(self, u128)
    }

    pub fn u8(&mut self) -> Result<u8> {
        if !self.is_empty() {
            let v = unsafe { *self.buf.get_unchecked(self.pos) };
            self.pos += 1;
            Ok(v)
        } else {
            Err(self.bound_error())
        }
    }

    pub fn slice(&'s mut self, size: usize) -> Result<&'a [u8]> {
        if self.len() >= size {
            let pos = self.pos;
            self.pos += size;
            Ok(unsafe { self.buf.get_unchecked(pos..pos + size) })
        } else {
            Err(self.bound_error())
        }
    }

    #[inline]
    fn bound_error(&self) -> Error {
        if self.orig.is_none() {
            Error::EndOfBuffer
        } else {
            Error::EndOfWindow
        }
    }
}