cyfs_lib/base/
select_request.rs

1use crate::*;
2use cyfs_base::*;
3
4use http_types::{Method, Request, Response, StatusCode, Url};
5use serde_json::{Map, Value};
6use std::fmt;
7use std::str::FromStr;
8
9#[derive(Debug, Clone)]
10pub struct SelectTimeRange {
11    // [begin, end)
12    pub begin: Option<u64>,
13    pub end: Option<u64>,
14}
15
16#[derive(Debug, Clone)]
17pub struct SelectFilter {
18    pub obj_type: Option<u16>,
19    pub obj_type_code: Option<ObjectTypeCode>,
20
21    pub dec_id: Option<ObjectId>,
22    pub owner_id: Option<ObjectId>,
23    pub author_id: Option<ObjectId>,
24
25    pub create_time: Option<SelectTimeRange>,
26    pub update_time: Option<SelectTimeRange>,
27    pub insert_time: Option<SelectTimeRange>,
28
29    // TODO 目前flags只支持全匹配
30    pub flags: Option<u32>,
31}
32
33impl Default for SelectFilter {
34    fn default() -> Self {
35        Self {
36            obj_type: None,
37            obj_type_code: None,
38
39            dec_id: None,
40            owner_id: None,
41            author_id: None,
42
43            create_time: None,
44            update_time: None,
45            insert_time: None,
46
47            flags: None,
48        }
49    }
50}
51
52impl fmt::Display for SelectFilter {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        if let Some(v) = &self.obj_type {
55            write!(f, "obj_type:{} ", v)?;
56        }
57        if let Some(v) = &self.obj_type_code {
58            write!(f, "obj_type_code:{} ", v.to_u16())?;
59        }
60
61        if let Some(v) = &self.dec_id {
62            write!(f, "dec_id:{} ", v.to_string())?;
63        }
64        if let Some(v) = &self.owner_id {
65            write!(f, "owner_id:{} ", v.to_string())?;
66        }
67        if let Some(v) = &self.author_id {
68            write!(f, "author_id:{} ", v.to_string())?;
69        }
70
71        if let Some(v) = &self.create_time {
72            write!(f, "create_time:{:?} ", v)?;
73        }
74        if let Some(v) = &self.update_time {
75            write!(f, "update_time:{:?} ", v)?;
76        }
77        if let Some(v) = &self.insert_time {
78            write!(f, "insert_time:{:?} ", v)?;
79        }
80
81        if let Some(v) = &self.flags {
82            write!(f, "flags:{} ", v)?;
83        }
84        Ok(())
85    }
86}
87
88#[derive(Debug, Clone)]
89pub struct SelectOption {
90    // 每页读取的数量
91    pub page_size: u16,
92
93    // 当前读取的页码,从0开始
94    pub page_index: u16,
95}
96
97impl Default for SelectOption {
98    fn default() -> Self {
99        Self {
100            page_size: 32_u16,
101            page_index: 0_u16,
102        }
103    }
104}
105
106impl fmt::Display for SelectOption {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        write!(f, "page_size:{} ", self.page_size)?;
109        write!(f, "page_index:{}", self.page_index)
110    }
111}
112
113
114#[derive(Debug, Clone, RawDecode, RawEncode)]
115pub struct SelectResponseObjectMetaInfo {
116    pub insert_time: u64,
117    pub create_dec_id: Option<ObjectId>,
118    pub context: Option<String>,
119    pub last_access_rpath: Option<String>,
120    pub access_string: Option<u32>,
121}
122
123#[derive(Debug, Clone, RawEncode, RawDecode)]
124pub struct SelectResponseObjectInfo {
125    pub meta: SelectResponseObjectMetaInfo,
126    pub object: Option<NONObjectInfo>,
127}
128
129impl SelectResponseObjectInfo {
130    fn from_meta(meta: SelectResponseObjectMetaInfo) -> Self {
131        Self {
132            meta,
133            object: None,
134        }
135    }
136
137    fn meta(&self) -> &SelectResponseObjectMetaInfo {
138        &self.meta
139    }
140}
141
142impl fmt::Display for SelectResponseObjectMetaInfo {
143    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144        write!(f, "insert_time:{}", self.insert_time)?;
145
146        if let Some(v) = &self.create_dec_id {
147            write!(f, ", create_dec_id:{} ", v)?;
148        }
149        if let Some(v) = &self.context {
150            write!(f, ", context:{} ", v)?;
151        }
152        if let Some(v) = &self.last_access_rpath {
153            write!(f, ", last_access_rpath:{} ", v)?;
154        }
155        write!(f, ", access:{:?}", self.access_string)?;
156
157        Ok(())
158    }
159}
160
161impl fmt::Display for SelectResponseObjectInfo {
162    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163        write!(f, "{} ", self.meta)?;
164
165        if let Some(obj) = &self.object {
166            write!(f, "object:{} ", obj)?;
167        }
168
169        Ok(())
170    }
171}
172
173impl JsonCodec<SelectResponseObjectMetaInfo> for SelectResponseObjectMetaInfo {
174    fn encode_json(&self) -> Map<String, Value> {
175        let mut obj = Map::new();
176
177        obj.insert(
178            "insert_time".to_owned(),
179            Value::String(self.insert_time.to_string()),
180        );
181
182        JsonCodecHelper::encode_option_string_field(&mut obj, "create_dec_id", self.create_dec_id.as_ref());
183        JsonCodecHelper::encode_option_string_field(&mut obj, "context", self.context.as_ref());
184        JsonCodecHelper::encode_option_string_field(&mut obj, "last_access_rpath", self.last_access_rpath.as_ref());
185        JsonCodecHelper::encode_option_number_field(&mut obj, "access", self.access_string);
186
187        obj
188    }
189
190    fn decode_json(obj: &Map<String, Value>) -> BuckyResult<Self> {
191        Ok(Self {
192            insert_time: JsonCodecHelper::decode_int_field(obj, "insert_time")?,
193            create_dec_id: JsonCodecHelper::decode_option_string_field(obj, "create_dec_id")?,
194            context: JsonCodecHelper::decode_option_string_field(obj, "context")?,
195            last_access_rpath: JsonCodecHelper::decode_option_string_field(obj, "last_access_rpath")?,
196            access_string: JsonCodecHelper::decode_option_int_field(obj, "access")?,
197        })
198    }
199}
200
201impl JsonCodec<SelectResponseObjectInfo> for SelectResponseObjectInfo {
202    fn encode_json(&self) -> Map<String, Value> {
203        let mut obj = Map::new();
204
205        JsonCodecHelper::encode_field(&mut obj, "meta", &self.meta);
206        let mut obj = self.meta().encode_json();
207        if let Some(object) = &self.object {
208            JsonCodecHelper::encode_field(&mut obj, "object", object);
209        }
210        obj
211    }
212
213    fn decode_json(obj: &Map<String, Value>) -> BuckyResult<Self> {
214        Ok(Self {
215            meta: JsonCodecHelper::decode_field(obj, "meta")?,
216            object: JsonCodecHelper::decode_option_field(obj, "object")?,
217        })
218    }
219}
220
221impl SelectResponseObjectInfo {
222    // 绑定对象,仅可执行一次
223    pub fn bind_object(&mut self, buf: Vec<u8>) -> BuckyResult<()> {
224        assert!(self.object.is_none());
225
226        let info = NONObjectInfo::new_from_object_raw(buf)?;
227        self.object = Some(info);
228
229        Ok(())
230    }
231}
232
233impl Default for SelectTimeRange {
234    fn default() -> Self {
235        Self {
236            begin: None,
237            end: None,
238        }
239    }
240}
241
242impl SelectTimeRange {
243    pub fn is_empty(&self) -> bool {
244        self.begin.is_none() && self.end.is_none()
245    }
246}
247
248impl ToString for SelectTimeRange {
249    fn to_string(&self) -> String {
250        if self.begin.is_some() && self.end.is_some() {
251            format!(
252                "{}:{}",
253                self.begin.as_ref().unwrap(),
254                self.end.as_ref().unwrap()
255            )
256        } else if self.begin.is_some() {
257            format!("{}:", self.begin.as_ref().unwrap())
258        } else if self.end.is_some() {
259            format!(":{}", self.end.as_ref().unwrap())
260        } else {
261            ":".to_owned()
262        }
263    }
264}
265
266impl FromStr for SelectTimeRange {
267    type Err = BuckyError;
268    fn from_str(s: &str) -> Result<Self, Self::Err> {
269        let parts: Vec<&str> = s.split(":").collect();
270        if parts.len() != 2 {
271            return Err(BuckyError::from(BuckyErrorCode::InvalidFormat));
272        }
273
274        let mut ret = Self {
275            begin: None,
276            end: None,
277        };
278
279        let begin = parts[0].trim();
280        if !begin.is_empty() {
281            let begin: u64 = begin.parse().map_err(|e| {
282                error!("decode time error: {} {}", begin, e);
283                BuckyError::from(BuckyErrorCode::InvalidFormat)
284            })?;
285
286            ret.begin = Some(begin);
287        }
288
289        let end = parts[1].trim();
290        if !end.is_empty() {
291            let end: u64 = end.parse().map_err(|e| {
292                error!("decode time error: {} {}", end, e);
293                BuckyError::from(BuckyErrorCode::InvalidFormat)
294            })?;
295
296            ret.end = Some(end);
297        }
298
299        Ok(ret)
300    }
301}
302
303pub struct SelectResponse {
304    pub objects: Vec<SelectResponseObjectInfo>,
305}
306
307impl fmt::Display for SelectResponse {
308    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309        write!(f, "size:{}", self.objects.len())?;
310        for item in &self.objects {
311            write!(f, ",{}", item)?;
312        }
313
314        Ok(())
315    }
316}
317
318impl SelectResponse {
319    pub fn encode_objects(http_resp: &mut Response, objects: Vec<SelectResponseObjectInfo>) -> BuckyResult<()> {
320        if objects.is_empty() {
321            return Ok(());
322        }
323
324        let buf = objects.to_vec()?;
325        
326        debug!(
327            "will send select all_buf: len={}, count={}",
328            buf.len(),
329            objects.len(),
330            //hex::encode(&all_buf)
331        );
332
333        http_resp.set_body(buf);
334
335        Ok(())
336    }
337
338    pub fn into_resonse(self) -> BuckyResult<Response> {
339        let mut resp = RequestorHelper::new_response(StatusCode::Ok);
340        if !self.objects.is_empty() {
341            Self::encode_objects(&mut resp, self.objects)?;
342        }
343
344        Ok(resp)
345    }
346
347    pub async fn from_respone(mut resp: Response) -> BuckyResult<Self> {
348        let all_buf = resp.body_bytes().await.map_err(|e| {
349            let msg = format!("read select resp body bytes error: {}", e);
350            error!("{}", msg);
351
352            BuckyError::new(BuckyErrorCode::IoError, msg)
353        })?;
354
355        let objects = if all_buf.len() > 0 {
356            let (objects, _) = Vec::raw_decode(&all_buf)?;
357            objects
358        } else {
359            vec![]
360        };
361        
362        debug!(
363            "recv select all_buf: len={}, count={}",
364            all_buf.len(),
365            objects.len(),
366        );
367
368        Ok(Self { objects })
369    }
370}
371
372pub struct SelectFilterUrlCodec;
373impl SelectFilterUrlCodec {
374    pub fn encode(url: &mut Url, filter: &SelectFilter) {
375        let mut query = url.query_pairs_mut();
376        if let Some(obj_type) = &filter.obj_type {
377            query.append_pair("obj-type", &obj_type.to_string());
378        }
379        if let Some(obj_type_code) = &filter.obj_type_code {
380            query.append_pair("obj-type-code", &obj_type_code.to_string());
381        }
382
383        if let Some(dec_id) = &filter.dec_id {
384            query.append_pair("dec-id", &dec_id.to_string());
385        }
386        if let Some(owner_id) = &filter.owner_id {
387            query.append_pair("owner-id", &owner_id.to_string());
388        }
389        if let Some(author_id) = &filter.author_id {
390            query.append_pair("author-id", &author_id.to_string());
391        }
392
393        if let Some(create_time) = &filter.create_time {
394            query.append_pair("create-time", &create_time.to_string());
395        }
396        if let Some(update_time) = &filter.update_time {
397            query.append_pair("update-time", &update_time.to_string());
398        }
399        if let Some(insert_time) = &filter.insert_time {
400            query.append_pair("insert-time", &insert_time.to_string());
401        }
402
403        if let Some(flags) = &filter.flags {
404            query.append_pair("flags", &flags.to_string());
405        }
406    }
407
408    pub fn decode(url: &Url) -> BuckyResult<SelectFilter> {
409        let mut obj_type = None;
410        let mut obj_type_code = None;
411
412        let mut dec_id = None;
413        let mut owner_id = None;
414        let mut author_id = None;
415
416        let mut create_time = None;
417        let mut update_time = None;
418        let mut insert_time = None;
419
420        let mut flags = None;
421
422        for (k, v) in url.query_pairs() {
423            match k.as_ref() {
424                "obj-type" => {
425                    obj_type = Some(RequestorHelper::decode_url_param(k, v)?);
426                }
427                "obj-type-code" => {
428                    obj_type_code = Some(RequestorHelper::decode_url_param(k, v)?);
429                }
430
431                "dec-id" => {
432                    dec_id = Some(RequestorHelper::decode_url_param(k, v)?);
433                }
434                "owner-id" => {
435                    owner_id = Some(RequestorHelper::decode_url_param(k, v)?);
436                }
437                "author-id" => {
438                    author_id = Some(RequestorHelper::decode_url_param(k, v)?);
439                }
440
441                "create-time" => {
442                    create_time = Some(RequestorHelper::decode_url_param(k, v)?);
443                }
444                "update-time" => {
445                    update_time = Some(RequestorHelper::decode_url_param(k, v)?);
446                }
447                "insert-time" => {
448                    insert_time = Some(RequestorHelper::decode_url_param(k, v)?);
449                }
450
451                "flags" => {
452                    flags = Some(RequestorHelper::decode_url_param(k, v)?);
453                }
454
455                _ => {
456                    warn!("unknown select filter param: {} = {}", k, v);
457                }
458            }
459        }
460
461        let ret = SelectFilter {
462            obj_type,
463            obj_type_code,
464
465            dec_id,
466            owner_id,
467            author_id,
468
469            create_time,
470            insert_time,
471            update_time,
472
473            flags,
474        };
475
476        Ok(ret)
477    }
478}
479
480pub struct SelectOptionCodec;
481
482impl SelectOptionCodec {
483    pub fn encode(req: &mut Request, opt: &Option<SelectOption>) {
484        if let Some(opt) = opt {
485            RequestorHelper::encode_header(req, cyfs_base::CYFS_PAGE_SIZE, &opt.page_size);
486            RequestorHelper::encode_header(req, cyfs_base::CYFS_PAGE_INDEX, &opt.page_index);
487        }
488    }
489
490    pub fn decode(req: &Request) -> BuckyResult<Option<SelectOption>> {
491        let page_size: Option<u16> =
492            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_PAGE_SIZE)?;
493        let page_index: Option<u16> =
494            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_PAGE_INDEX)?;
495
496        let ret = if page_size.is_some() || page_index.is_some() {
497            let mut select_opt = SelectOption::default();
498            if page_size.is_some() {
499                select_opt.page_size = page_size.unwrap();
500            }
501            if page_index.is_some() {
502                select_opt.page_index = page_index.unwrap();
503            }
504            Some(select_opt)
505        } else {
506            None
507        };
508        Ok(ret)
509    }
510}
511
512pub struct SelectEncoder {
513    service_url: Url,
514}
515
516impl SelectEncoder {
517    pub fn new(service_url: Url) -> Self {
518        Self { service_url }
519    }
520
521    pub fn encode_select_request(&self, req: &SelectFilter, opt: Option<&SelectOption>) -> Request {
522        let mut http_req = Request::new(Method::Get, self.service_url.clone());
523
524        // TODO: 应该有通用处理
525        // 允许浏览器fetch API读取私有header
526        http_req.append_header("Access-Control-Allow-Headers", cyfs_base::CYFS_OBJECTS);
527        http_req.append_header("Access-Control-Expose-Headers", cyfs_base::CYFS_OBJECTS);
528
529        RequestorHelper::encode_opt_header(&mut http_req, cyfs_base::CYFS_OBJ_TYPE, &req.obj_type);
530        RequestorHelper::encode_opt_header(
531            &mut http_req,
532            cyfs_base::CYFS_OBJ_TYPE_CODE,
533            &req.obj_type_code,
534        );
535
536        RequestorHelper::encode_opt_header(
537            &mut http_req,
538            cyfs_base::CYFS_FILTER_DEC_ID,
539            &req.dec_id,
540        );
541        RequestorHelper::encode_opt_header(&mut http_req, cyfs_base::CYFS_OWNER_ID, &req.owner_id);
542        RequestorHelper::encode_opt_header(
543            &mut http_req,
544            cyfs_base::CYFS_AUTHOR_ID,
545            &req.author_id,
546        );
547
548        RequestorHelper::encode_opt_header(
549            &mut http_req,
550            cyfs_base::CYFS_CREATE_TIME,
551            &req.create_time,
552        );
553        RequestorHelper::encode_opt_header(
554            &mut http_req,
555            cyfs_base::CYFS_UPDATE_TIME,
556            &req.update_time,
557        );
558        RequestorHelper::encode_opt_header(
559            &mut http_req,
560            cyfs_base::CYFS_INSERT_TIME,
561            &req.insert_time,
562        );
563
564        RequestorHelper::encode_opt_header(&mut http_req, cyfs_base::CYFS_FILTER_FLAGS, &req.flags);
565
566        if opt.is_some() {
567            let opt = opt.unwrap();
568
569            RequestorHelper::encode_header(
570                &mut http_req,
571                cyfs_base::CYFS_PAGE_SIZE,
572                &opt.page_size,
573            );
574            RequestorHelper::encode_header(
575                &mut http_req,
576                cyfs_base::CYFS_PAGE_INDEX,
577                &opt.page_index,
578            );
579        }
580
581        http_req
582    }
583}
584
585pub struct SelectDecoder;
586
587impl SelectDecoder {
588    pub fn decode_select_request(req: &Request) -> BuckyResult<(SelectFilter, SelectOption)> {
589        // SelectFilter
590        let obj_type: Option<u16> =
591            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_OBJ_TYPE)?;
592        let obj_type_code: Option<ObjectTypeCode> =
593            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_OBJ_TYPE_CODE)?;
594
595        let dec_id: Option<ObjectId> =
596            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_FILTER_DEC_ID)?;
597        let owner_id: Option<ObjectId> =
598            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_OWNER_ID)?;
599        let author_id: Option<ObjectId> =
600            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_AUTHOR_ID)?;
601
602        let create_time: Option<SelectTimeRange> =
603            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_CREATE_TIME)?;
604        let update_time: Option<SelectTimeRange> =
605            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_UPDATE_TIME)?;
606        let insert_time: Option<SelectTimeRange> =
607            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_INSERT_TIME)?;
608
609        let flags: Option<u32> =
610            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_FILTER_FLAGS)?;
611
612        // SelectOption
613        let page_size: Option<u16> =
614            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_PAGE_SIZE)?;
615        let page_index: Option<u16> =
616            RequestorHelper::decode_optional_header(req, cyfs_base::CYFS_PAGE_INDEX)?;
617
618        let select_req = SelectFilter {
619            obj_type,
620            obj_type_code,
621
622            dec_id,
623            owner_id,
624            author_id,
625
626            create_time,
627            update_time,
628            insert_time,
629
630            flags,
631        };
632
633        let mut select_opt = SelectOption::default();
634        if page_size.is_some() {
635            select_opt.page_size = page_size.unwrap();
636        }
637        if page_index.is_some() {
638            select_opt.page_index = page_index.unwrap();
639        }
640
641        Ok((select_req, select_opt))
642    }
643}
644
645impl JsonCodec<SelectTimeRange> for SelectTimeRange {
646    fn encode_json(&self) -> Map<String, Value> {
647        let mut obj = Map::new();
648
649        JsonCodecHelper::encode_option_number_field(&mut obj, "begin", self.begin);
650        JsonCodecHelper::encode_option_number_field(&mut obj, "end", self.end);
651
652        obj
653    }
654
655    fn decode_json(obj: &Map<String, Value>) -> BuckyResult<SelectTimeRange> {
656        Ok(Self {
657            begin: JsonCodecHelper::decode_option_int_field(obj, "begin")?,
658            end: JsonCodecHelper::decode_option_int_field(obj, "end")?,
659        })
660    }
661}
662
663impl JsonCodec<SelectFilter> for SelectFilter {
664    fn encode_json(&self) -> Map<String, Value> {
665        let mut obj = Map::new();
666
667        JsonCodecHelper::encode_option_number_field(&mut obj, "obj_type", self.obj_type);
668        JsonCodecHelper::encode_option_number_field(
669            &mut obj,
670            "obj_type_code",
671            self.obj_type_code.as_ref().map(|v| v.to_u16()),
672        );
673
674        JsonCodecHelper::encode_option_string_field(&mut obj, "dec_id", self.dec_id.as_ref());
675        JsonCodecHelper::encode_option_string_field(&mut obj, "owner_id", self.owner_id.as_ref());
676        JsonCodecHelper::encode_option_string_field(&mut obj, "author_id", self.author_id.as_ref());
677
678        JsonCodecHelper::encode_option_field(&mut obj, "create_time", self.create_time.as_ref());
679        JsonCodecHelper::encode_option_field(&mut obj, "update_time", self.update_time.as_ref());
680        JsonCodecHelper::encode_option_field(&mut obj, "insert_time", self.insert_time.as_ref());
681
682        JsonCodecHelper::encode_option_number_field(&mut obj, "flags", self.flags);
683
684        obj
685    }
686
687    fn decode_json(obj: &Map<String, Value>) -> BuckyResult<SelectFilter> {
688        let obj_type_code: Option<u16> =
689            JsonCodecHelper::decode_option_int_field(obj, "obj_type_code")?;
690        Ok(Self {
691            obj_type: JsonCodecHelper::decode_option_int_field(obj, "obj_type")?,
692            obj_type_code: obj_type_code.map(|v| v.into()),
693
694            dec_id: JsonCodecHelper::decode_option_string_field(obj, "dec_id")?,
695            owner_id: JsonCodecHelper::decode_option_string_field(obj, "owner_id")?,
696            author_id: JsonCodecHelper::decode_option_string_field(obj, "author_id")?,
697
698            create_time: JsonCodecHelper::decode_option_field(obj, "create_time")?,
699            update_time: JsonCodecHelper::decode_option_field(obj, "update_time")?,
700            insert_time: JsonCodecHelper::decode_option_field(obj, "insert_time")?,
701
702            flags: JsonCodecHelper::decode_option_int_field(obj, "flags")?,
703        })
704    }
705}
706
707impl JsonCodec<SelectOption> for SelectOption {
708    fn encode_json(&self) -> Map<String, Value> {
709        let mut obj = Map::new();
710
711        JsonCodecHelper::encode_number_field(&mut obj, "page_index", self.page_index);
712        JsonCodecHelper::encode_number_field(&mut obj, "page_size", self.page_size);
713
714        obj
715    }
716
717    fn decode_json(obj: &Map<String, Value>) -> BuckyResult<SelectOption> {
718        Ok(Self {
719            page_index: JsonCodecHelper::decode_int_field(obj, "page_index")?,
720            page_size: JsonCodecHelper::decode_int_field(obj, "page_size")?,
721        })
722    }
723}