#[cfg(feature = "pub-response-field")]
pub(crate) mod pb;
#[cfg(not(feature = "pub-response-field"))]
mod pb;
pub mod auth;
pub mod cluster;
pub mod election;
pub mod kv;
pub mod lease;
pub mod lock;
pub mod maintenance;
pub mod watch;
use crate::error::Result;
use pb::etcdserverpb::ResponseHeader as PbResponseHeader;
use pb::mvccpb::KeyValue as PbKeyValue;
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct ResponseHeader(PbResponseHeader);
impl ResponseHeader {
        #[inline]
    pub(crate) const fn new(header: PbResponseHeader) -> Self {
        Self(header)
    }
        #[inline]
    pub const fn cluster_id(&self) -> u64 {
        self.0.cluster_id
    }
        #[inline]
    pub const fn member_id(&self) -> u64 {
        self.0.member_id
    }
                    #[inline]
    pub const fn revision(&self) -> i64 {
        self.0.revision
    }
        #[inline]
    pub const fn raft_term(&self) -> u64 {
        self.0.raft_term
    }
}
impl From<&PbResponseHeader> for &ResponseHeader {
    #[inline]
    fn from(src: &PbResponseHeader) -> Self {
        unsafe { &*(src as *const _ as *const ResponseHeader) }
    }
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct KeyValue(PbKeyValue);
impl KeyValue {
        #[inline]
    pub(crate) const fn new(kv: PbKeyValue) -> Self {
        Self(kv)
    }
        #[inline]
    pub fn key(&self) -> &[u8] {
        &self.0.key
    }
        #[inline]
    pub fn key_str(&self) -> Result<&str> {
        std::str::from_utf8(self.key()).map_err(From::from)
    }
                            #[inline]
    pub unsafe fn key_str_unchecked(&self) -> &str {
        std::str::from_utf8_unchecked(self.key())
    }
        #[inline]
    pub fn value(&self) -> &[u8] {
        &self.0.value
    }
        #[inline]
    pub fn value_str(&self) -> Result<&str> {
        std::str::from_utf8(self.value()).map_err(From::from)
    }
                            #[inline]
    pub unsafe fn value_str_unchecked(&self) -> &str {
        std::str::from_utf8_unchecked(self.value())
    }
        pub fn into_key_value(self) -> (Vec<u8>, Vec<u8>) {
        (self.0.key, self.0.value)
    }
        #[inline]
    pub const fn create_revision(&self) -> i64 {
        self.0.create_revision
    }
        #[inline]
    pub const fn mod_revision(&self) -> i64 {
        self.0.mod_revision
    }
                #[inline]
    pub const fn version(&self) -> i64 {
        self.0.version
    }
                #[inline]
    pub const fn lease(&self) -> i64 {
        self.0.lease
    }
}
impl From<&PbKeyValue> for &KeyValue {
    #[inline]
    fn from(src: &PbKeyValue) -> Self {
        unsafe { &*(src as *const _ as *const KeyValue) }
    }
}
impl From<&mut PbKeyValue> for &mut KeyValue {
    #[inline]
    fn from(src: &mut PbKeyValue) -> Self {
        unsafe { &mut *(src as *mut _ as *mut KeyValue) }
    }
}
#[inline]
fn get_prefix(key: &[u8]) -> Vec<u8> {
    for (i, v) in key.iter().enumerate().rev() {
        if *v < 0xFF {
            let mut end = Vec::from(&key[..=i]);
            end[i] = *v + 1;
            return end;
        }
    }
        vec![0]
}
#[derive(Debug, Default, Clone)]
struct KeyRange {
    key: Vec<u8>,
    range_end: Vec<u8>,
    with_prefix: bool,
    with_from_key: bool,
    with_all_keys: bool,
}
impl KeyRange {
    #[inline]
    pub const fn new() -> Self {
        KeyRange {
            key: Vec::new(),
            range_end: Vec::new(),
            with_prefix: false,
            with_from_key: false,
            with_all_keys: false,
        }
    }
        #[inline]
    pub fn with_key(&mut self, key: impl Into<Vec<u8>>) {
        self.key = key.into();
    }
            #[inline]
    pub fn with_range(&mut self, end_key: impl Into<Vec<u8>>) {
        self.range_end = end_key.into();
        self.with_prefix = false;
        self.with_from_key = false;
        self.with_all_keys = false;
    }
        #[inline]
    pub fn with_from_key(&mut self) {
        self.with_from_key = true;
        self.with_prefix = false;
        self.with_all_keys = false;
    }
        #[inline]
    pub fn with_prefix(&mut self) {
        self.with_prefix = true;
        self.with_from_key = false;
        self.with_all_keys = false;
    }
        #[inline]
    pub fn with_all_keys(&mut self) {
        self.with_all_keys = true;
        self.with_prefix = false;
        self.with_from_key = false;
    }
        #[inline]
    pub fn build(mut self) -> (Vec<u8>, Vec<u8>) {
        if self.with_all_keys {
            self.key = vec![b'\0'];
            self.range_end = vec![b'\0'];
        } else if self.with_from_key {
            if self.key.is_empty() {
                self.key = vec![b'\0'];
            }
            self.range_end = vec![b'\0'];
        } else if self.with_prefix {
            if self.key.is_empty() {
                self.key = vec![b'\0'];
                self.range_end = vec![b'\0'];
            } else {
                self.range_end = get_prefix(&self.key);
            }
        }
        (self.key, self.range_end)
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_get_prefix() {
        assert_eq!(get_prefix(b"foo1").as_slice(), b"foo2");
        assert_eq!(get_prefix(b"\xFF").as_slice(), b"\0");
        assert_eq!(get_prefix(b"foo\xFF").as_slice(), b"fop");
    }
}