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
112
113
114
115
116
use redis::resp;

use btoi;
use futures::unsync::mpsc::SendError;
use net2::TcpBuilder;
use tokio::net::TcpListener;

use std::convert::From;
use std::io;
use std::net;
use std::net::SocketAddr;
use std::num;
use std::result;

#[derive(Debug)]
pub enum Error {
    None,
    MoreData,
    NotSupport,
    BadMsg,
    BadKey,
    BadCmd,
    BadConfig,
    BadSlotsMap,
    ClusterDown,
    IoError(io::Error),
    Critical,
    StrParseIntError(num::ParseIntError),
    ParseIntError(btoi::ParseIntegerError),
    SendError(SendError<resp::Resp>),
    AddrParseError(net::AddrParseError),
}

impl From<net::AddrParseError> for Error {
    fn from(oe: net::AddrParseError) -> Error {
        Error::AddrParseError(oe)
    }
}

impl From<SendError<resp::Resp>> for Error {
    fn from(oe: SendError<resp::Resp>) -> Error {
        Error::SendError(oe)
    }
}

impl From<io::Error> for Error {
    fn from(oe: io::Error) -> Error {
        Error::IoError(oe)
    }
}

impl From<btoi::ParseIntegerError> for Error {
    fn from(oe: btoi::ParseIntegerError) -> Error {
        Error::ParseIntError(oe)
    }
}

impl From<num::ParseIntError> for Error {
    fn from(oe: num::ParseIntError) -> Error {
        Error::StrParseIntError(oe)
    }
}

pub type AsResult<T> = result::Result<T, Error>;

const LOWER_BEGIN: u8 = b'a';
const LOWER_END: u8 = b'z';
const UPPER_BEGIN: u8 = b'A';
const UPPER_END: u8 = b'Z';
const UPPER_TO_LOWER: u8 = b'a' - b'A';

pub fn update_to_upper(src: &mut [u8]) {
    for b in src {
        if *b < LOWER_BEGIN || *b > LOWER_END {
            continue;
        }
        *b -= UPPER_TO_LOWER;
    }
}

pub fn update_to_lower(src: &mut [u8]) {
    for b in src {
        if *b < UPPER_BEGIN || *b > UPPER_END {
            continue;
        }
        *b += UPPER_TO_LOWER;
    }
}

#[cfg(windows)]
pub fn create_reuse_port_listener(addr: &SocketAddr) -> Result<TcpListener, std::io::Error> {
    let builder = TcpBuilder::new_v4()?;
    let std_listener = builder
        .reuse_address(true)
        .expect("os not support SO_REUSEADDR")
        .bind(addr)?
        .listen(std::i32::MAX)?;
    let hd = tokio::reactor::Handle::current();
    TcpListener::from_std(std_listener, &hd)
}

#[cfg(not(windows))]
pub fn create_reuse_port_listener(addr: &SocketAddr) -> Result<TcpListener, std::io::Error> {
    use net2::unix::UnixTcpBuilderExt;

    let builder = TcpBuilder::new_v4()?;
    let std_listener = builder
        .reuse_address(true)
        .expect("os not support SO_REUSEADDR")
        .reuse_port(true)
        .expect("os not support SO_REUSEPORT")
        .bind(addr)?
        .listen(std::i32::MAX)?;
    let hd = tokio::reactor::Handle::current();
    TcpListener::from_std(std_listener, &hd)
}