1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
use std::mem::size_of;

pub const HEADER_SIZE: usize = 25;
pub const MAGIC_MARKER: u32 = 0xEEEF_FEEE;
pub const MAGIC_MARKER_BYTES: [u8; 4] = [0xEE, 0xFE, 0xEF, 0xEE];

#[derive(PartialEq, Debug)]
pub enum ErrorQueue {
    NotReady = -911,
    AlreadyOpen = -8,
    FailWrite = -7,
    InvalidChecksum = -6,
    FailReadTailMessage = -5,
    FailOpen = -4,
    FailRead = -3,
    NotFound = -2,
    Other = -1,
}

#[derive(PartialEq, Copy, Clone)]
pub enum Mode {
    Read = 0,
    ReadWrite = 1,
    Default = 2,
}

#[derive(PartialEq, Debug)]
#[repr(u8)]
pub enum MsgType {
    String = b'S',
    Object = b'O',
}

impl From<u8> for MsgType {
    fn from(t: u8) -> Self {
        if t == b'O' {
            MsgType::Object
        } else {
            MsgType::String
        }
    }
}

impl MsgType {
    fn as_u8(&self) -> u8 {
        if *self == MsgType::Object {
            b'O'
        } else {
            b'S'
        }
    }
}

impl ErrorQueue {
    pub fn as_str(&self) -> &'static str {
        match *self {
            ErrorQueue::NotFound => "not found",
            ErrorQueue::Other => "other error",
            ErrorQueue::AlreadyOpen => "already open",
            ErrorQueue::FailOpen => "fail open",
            ErrorQueue::FailRead => "fail read",
            ErrorQueue::FailWrite => "fail write",
            ErrorQueue::NotReady => "not ready",
            ErrorQueue::FailReadTailMessage => "fail read tail message",
            ErrorQueue::InvalidChecksum => "invalid checksum",
        }
    }
}

#[derive(Debug)]
pub struct Header {
    pub start_pos: u64,
    pub msg_length: u32,
    pub magic_marker: u32,
    pub count_pushed: u32,
    pub crc: u32,
    pub msg_type: MsgType,
}

impl Header {
    pub fn create_from_buf(buf: &[u8]) -> Self {
        Header {
            start_pos: u64::from_ne_bytes([buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]]),
            msg_length: u32::from_ne_bytes([buf[8], buf[9], buf[10], buf[11]]),
            magic_marker: u32::from_ne_bytes([buf[12], buf[13], buf[14], buf[15]]),
            count_pushed: u32::from_ne_bytes([buf[16], buf[17], buf[18], buf[19]]),
            msg_type: MsgType::from(buf[20]),
            crc: u32::from_ne_bytes([buf[21], buf[22], buf[23], buf[24]]),
        }
    }

    pub fn to_buf(&self, buf: &mut [u8; HEADER_SIZE]) {
        let mut l = 0;
        let mut r = size_of::<u64>();
        buf[l..r].clone_from_slice(&u64::to_ne_bytes(self.start_pos));
        l = r;
        r += size_of::<u32>();
        buf[l..r].clone_from_slice(&u32::to_ne_bytes(self.msg_length));
        l = r;
        r += size_of::<u32>();
        buf[l..r].clone_from_slice(&[0xEE, 0xFE, 0xEF, 0xEE]);
        l = r;
        r += size_of::<u32>();
        buf[l..r].clone_from_slice(&u32::to_ne_bytes(self.count_pushed));
        buf[r] = self.msg_type.as_u8();
        buf[r + 1] = 0;
        buf[r + 2] = 0;
        buf[r + 3] = 0;
        buf[r + 4] = 0;
    }
}