kf_protocol_api/
api.rs

1use std::default::Default;
2use std::io::Error as IoError;
3use std::io::ErrorKind;
4use std::fs::File;
5use std::io::Cursor;
6use std::path::Path;
7use std::io::Read;
8use std::fmt::Debug;
9use std::fmt;
10use std::convert::TryFrom;
11
12use log::trace;
13use log::debug;
14
15use kf_protocol::Decoder;
16use kf_protocol::Encoder;
17use kf_protocol::bytes::Buf;
18use kf_protocol_derive::Decode;
19use kf_protocol_derive::Encode;
20
21
22pub trait Request: Encoder + Decoder + Debug {
23
24    const API_KEY: u16;
25
26    const DEFAULT_API_VERSION: i16 = 0;
27    const MIN_API_VERSION: i16 = 0;
28    const MAX_API_VERSION: i16 = -1;
29
30    type Response: Encoder + Decoder + Debug ;
31
32}
33
34
35pub trait KfRequestMessage: Sized + Default 
36
37{
38        type ApiKey: Decoder + Debug ;
39       
40        fn decode_with_header<T>(src: &mut T, header: RequestHeader) -> Result<Self,IoError>
41        where
42                Self: Default + Sized,
43                Self::ApiKey: Sized,
44                T: Buf;
45
46        
47        fn decode_from<T>(src: &mut T) -> Result<Self,IoError>
48                where T: Buf,
49                    
50        {
51                let header = RequestHeader::decode_from(src,0)?;
52                Self::decode_with_header(src,header)
53
54        }
55
56        fn decode_from_file<P: AsRef<Path>>(file_name: P) -> Result<Self,IoError> {
57
58                debug!("decoding from file: {:#?}", file_name.as_ref());
59                let mut f = File::open(file_name)?;
60                let mut buffer: [u8; 1000] = [0; 1000];
61
62                f.read(&mut buffer)?;
63
64                let data = buffer.to_vec();
65                let mut src = Cursor::new(&data);
66
67                let mut size: i32 = 0;
68                size.decode(&mut src,0)?;
69                trace!("decoded request size: {} bytes", size);
70
71                if src.remaining() < size as usize {
72                         return Err(IoError::new(
73                                ErrorKind::UnexpectedEof,
74                                "not enought bytes for request message",
75                        ));
76                }
77
78
79                Self::decode_from(&mut src)
80        }
81
82}
83
84pub trait KfApiKey: Sized + Encoder + Decoder + TryFrom<u16> {
85    
86}
87
88
89
90
91#[derive(Debug, Encode, Decode, Default)]
92pub struct RequestHeader {
93    api_key: u16,
94    api_version: i16,
95    correlation_id: i32,
96    client_id: String,
97}
98
99impl fmt::Display for RequestHeader {
100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101        write!(f,"api: {} client: {}",self.api_key,self.client_id)
102    }
103}
104
105
106
107impl RequestHeader {
108
109    
110    pub fn new(api_key: u16) -> Self {
111        // TODO: generate random client id
112        Self::new_with_client(api_key,"dummy".to_owned())
113    }
114
115    pub fn new_with_client<T>(api_key: u16,client_id: T) -> Self 
116        where T: Into<String>
117    {
118        RequestHeader {
119            api_key,
120            api_version: 1,
121            correlation_id: 1,
122
123            client_id: client_id.into()
124        }
125    }
126
127    pub fn api_key(&self) -> u16 {
128        self.api_key
129    }
130
131    pub fn api_version(&self) -> i16 {
132        self.api_version
133    }
134
135    pub fn set_api_version(&mut self,version: i16) -> &mut Self {
136        self.api_version = version;
137        self
138    }
139
140    pub fn correlation_id(&self) -> i32 {
141        self.correlation_id
142    }
143
144    pub fn set_correlation_id(&mut self,id: i32) -> &mut Self  {
145        self.correlation_id = id;
146        self
147    }
148
149    pub fn client_id(&self) -> &String {
150        &self.client_id
151    }
152
153    pub fn set_client_id<T>(&mut self,client_id: T) -> &mut Self
154        where T: Into<String>
155    {
156        self.client_id = client_id.into();
157        self
158    }
159    
160}
161
162impl From<&RequestHeader> for i32 {
163    fn from(header: &RequestHeader) -> i32 {
164        header.correlation_id()
165    }
166}