1mod convert;
2mod faststr_map;
3mod kv;
4mod type_map;
5
6use std::{fmt, sync::Arc};
7
8use ahash::AHashMap;
9use convert::{Converter, HttpConverter, RpcConverter};
10use faststr::FastStr;
11pub use faststr_map::FastStrMap;
12use kv::Node;
13use paste::paste;
14pub use type_map::TypeMap;
15
16pub mod backward;
17pub mod forward;
18pub use backward::Backward;
19pub use forward::Forward;
20
21#[cfg(feature = "task_local")]
22tokio::task_local! {
23 pub static METAINFO: std::cell::RefCell<MetaInfo>;
24}
25
26pub const RPC_PREFIX_PERSISTENT: &str = "RPC_PERSIST_";
29pub const RPC_PREFIX_TRANSIENT: &str = "RPC_TRANSIT_";
30pub const RPC_PREFIX_BACKWARD: &str = "RPC_BACKWARD_";
31pub const HTTP_PREFIX_PERSISTENT: &str = "rpc-persist-";
32pub const HTTP_PREFIX_TRANSIENT: &str = "rpc-transit-";
33pub const HTTP_PREFIX_BACKWARD: &str = "rpc-backward-";
34
35const DEFAULT_MAP_SIZE: usize = 10;
36
37#[derive(Default)]
65pub struct MetaInfo {
66 parent: Option<Arc<MetaInfo>>,
69 tmap: Option<TypeMap>,
70 smap: Option<AHashMap<FastStr, FastStr>>, faststr_tmap: Option<FastStrMap>, forward_node: Option<kv::Node>,
76 backward_node: Option<kv::Node>,
77}
78
79impl MetaInfo {
80 #[inline]
82 pub fn new() -> MetaInfo {
83 Default::default()
84 }
85
86 #[inline]
92 pub fn from(parent: Arc<MetaInfo>) -> MetaInfo {
93 let forward_node = parent.forward_node.clone();
94 let backward_node = parent.backward_node.clone();
95 MetaInfo {
96 parent: Some(parent),
97 tmap: None,
98 smap: None,
99 faststr_tmap: None,
100
101 forward_node,
102 backward_node,
103 }
104 }
105
106 #[inline]
112 pub fn derive(mut self) -> (MetaInfo, MetaInfo) {
113 if self.tmap.is_none() && self.smap.is_none() && self.faststr_tmap.is_none() {
114 let new = MetaInfo {
116 parent: self.parent.clone(),
117 tmap: None,
118 smap: None,
119 faststr_tmap: None,
120 forward_node: self.forward_node.clone(),
121 backward_node: self.backward_node.clone(),
122 };
123 (self, new)
124 } else {
125 let forward_node = self.forward_node.take();
126 let backward_node = self.backward_node.take();
127 let mi = Arc::new(self);
128 (
129 MetaInfo::from_node(mi.clone(), forward_node.clone(), backward_node.clone()),
130 MetaInfo::from_node(mi, forward_node, backward_node),
131 )
132 }
133 }
134
135 fn from_node(
137 parent: Arc<MetaInfo>,
138 forward_node: Option<kv::Node>,
139 backward_node: Option<kv::Node>,
140 ) -> MetaInfo {
141 MetaInfo {
142 parent: Some(parent),
143 tmap: None,
144 smap: None,
145 faststr_tmap: None,
146
147 forward_node,
148 backward_node,
149 }
150 }
151
152 #[inline]
154 pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) {
155 self.tmap
156 .get_or_insert_with(|| TypeMap::with_capacity(DEFAULT_MAP_SIZE))
157 .insert(val);
158 }
159
160 #[inline]
162 pub fn insert_faststr<T: Send + Sync + 'static>(&mut self, val: FastStr) {
163 self.faststr_tmap
164 .get_or_insert_with(|| FastStrMap::with_capacity(DEFAULT_MAP_SIZE))
165 .insert::<T>(val);
166 }
167
168 #[inline]
170 pub fn insert_string(&mut self, key: FastStr, val: FastStr) {
171 self.smap
172 .get_or_insert_with(|| AHashMap::with_capacity(DEFAULT_MAP_SIZE))
173 .insert(key, val);
174 }
175
176 #[inline]
178 pub fn contains<T: 'static>(&self) -> bool {
179 if self
180 .tmap
181 .as_ref()
182 .map(|tmap| tmap.contains::<T>())
183 .unwrap_or(false)
184 {
185 return true;
186 }
187 self.parent
188 .as_ref()
189 .map(|parent| parent.as_ref().contains::<T>())
190 .unwrap_or(false)
191 }
192
193 #[inline]
195 pub fn contains_faststr<T: 'static>(&self) -> bool {
196 if self
197 .faststr_tmap
198 .as_ref()
199 .map(|faststr_tmap| faststr_tmap.contains::<T>())
200 .unwrap_or(false)
201 {
202 return true;
203 }
204 self.parent
205 .as_ref()
206 .map(|parent| parent.as_ref().contains_faststr::<T>())
207 .unwrap_or(false)
208 }
209
210 #[inline]
212 pub fn contains_string<K: AsRef<str>>(&self, key: K) -> bool {
213 if self
214 .smap
215 .as_ref()
216 .map(|smap| smap.contains_key(key.as_ref()))
217 .unwrap_or(false)
218 {
219 return true;
220 }
221 self.parent
222 .as_ref()
223 .map(|parent| parent.as_ref().contains_string(key))
224 .unwrap_or(false)
225 }
226
227 #[inline]
229 pub fn get<T: 'static>(&self) -> Option<&T> {
230 self.tmap.as_ref().and_then(|tmap| tmap.get()).or_else(|| {
231 self.parent
232 .as_ref()
233 .and_then(|parent| parent.as_ref().get::<T>())
234 })
235 }
236
237 #[inline]
240 pub fn remove<T: 'static>(&mut self) -> Option<T> {
241 self.tmap.as_mut().and_then(|tmap| tmap.remove::<T>())
242 }
243
244 #[inline]
246 pub fn get_faststr<T: 'static>(&self) -> Option<&FastStr> {
247 self.faststr_tmap
248 .as_ref()
249 .and_then(|faststr_tmap: &FastStrMap| faststr_tmap.get::<T>())
250 .or_else(|| {
251 self.parent
252 .as_ref()
253 .and_then(|parent| parent.as_ref().get_faststr::<T>())
254 })
255 }
256
257 #[inline]
260 pub fn remove_faststr<T: 'static>(&mut self) -> Option<FastStr> {
261 self.faststr_tmap
262 .as_mut()
263 .and_then(|faststr_tmap| faststr_tmap.remove::<T>())
264 }
265
266 #[inline]
268 pub fn get_string<K: AsRef<str>>(&self, key: K) -> Option<&FastStr> {
269 self.smap
270 .as_ref()
271 .and_then(|smap| smap.get(key.as_ref()))
272 .or_else(|| {
273 self.parent
274 .as_ref()
275 .and_then(|parent| parent.as_ref().get_string(key))
276 })
277 }
278
279 #[inline]
282 pub fn remove_string<K: AsRef<str>>(&mut self, key: K) -> Option<FastStr> {
283 self.smap
284 .as_mut()
285 .and_then(|smap| smap.remove(key.as_ref()))
286 }
287
288 #[inline]
291 pub fn clear(&mut self) {
292 self.parent = None;
293 if let Some(tmap) = self.tmap.as_mut() {
294 tmap.clear()
295 }
296 if let Some(smap) = self.smap.as_mut() {
297 smap.clear()
298 }
299 if let Some(faststr_tmap) = self.faststr_tmap.as_mut() {
300 faststr_tmap.clear()
301 }
302 if let Some(forward_node) = self.forward_node.as_mut() {
303 forward_node.clear()
304 }
305 if let Some(backward_node) = self.backward_node.as_mut() {
306 backward_node.clear()
307 }
308 }
309
310 #[inline]
313 pub fn extend(&mut self, other: MetaInfo) {
314 if let Some(tmap) = other.tmap {
315 self.tmap
316 .get_or_insert_with(|| TypeMap::with_capacity(DEFAULT_MAP_SIZE))
317 .extend(tmap);
318 }
319
320 if let Some(smap) = other.smap {
321 self.smap
322 .get_or_insert_with(|| AHashMap::with_capacity(DEFAULT_MAP_SIZE))
323 .extend(smap);
324 }
325
326 if let Some(faststr_tmap) = other.faststr_tmap {
327 self.faststr_tmap
328 .get_or_insert_with(|| FastStrMap::with_capacity(DEFAULT_MAP_SIZE))
329 .extend(faststr_tmap);
330 }
331
332 if let Some(node) = other.forward_node {
333 if self.forward_node.is_none() {
334 self.forward_node = Some(node);
335 } else {
336 self.forward_node.as_mut().unwrap().extend(node);
337 }
338 }
339
340 if let Some(node) = other.backward_node {
341 if self.backward_node.is_none() {
342 self.backward_node = Some(node);
343 } else {
344 self.backward_node.as_mut().unwrap().extend(node);
345 }
346 }
347 }
348
349 fn ensure_forward_node(&mut self) {
350 if self.forward_node.is_none() {
351 self.forward_node = Some(Node::default())
352 }
353 }
354
355 fn ensure_backward_node(&mut self) {
356 if self.backward_node.is_none() {
357 self.backward_node = Some(Node::default())
358 }
359 }
360}
361
362macro_rules! get_impl {
363 ($name:ident,$node:ident,$func_name:ident) => {
364 paste! {
365 #[inline]
366 fn [<get_ $name>]<K: AsRef<str>>(&self, key: K) -> Option<FastStr> {
367 match self.[<$node _node>].as_ref() {
368 Some(node) => node.[<get_ $func_name>](key),
369 None => None,
370 }
371 }
372 }
373 };
374}
375
376macro_rules! set_impl {
377 ($name:ident,$node:ident,$func_name:ident) => {
378 paste! {
379 #[inline]
380 fn [<set_ $name>]<K: Into<FastStr>, V: Into<FastStr>>(
381 &mut self,
382 key: K,
383 value: V,
384 ) {
385 self.[<ensure_ $node _node>]();
386 self.[<$node _node>]
387 .as_mut()
388 .unwrap()
389 .[<set_ $func_name>](key, value)
390 }
391 }
392 };
393}
394
395macro_rules! del_impl {
396 ($name:ident,$node:ident,$func_name:ident) => {
397 paste! {
398 #[inline]
399 fn [<del_ $name>]<K: AsRef<str>>(&mut self, key: K) -> Option<FastStr> {
400 if let Some(node) = self.[<$node _node>].as_mut() {
401 node.[<del_ $func_name>](key)
402 } else {
403 None
404 }
405 }
406 }
407 };
408}
409
410impl forward::Forward for MetaInfo {
411 get_impl!(persistent, forward, persistent);
412 get_impl!(transient, forward, transient);
413 get_impl!(upstream, forward, stale);
414
415 set_impl!(persistent, forward, persistent);
416 set_impl!(transient, forward, transient);
417 set_impl!(upstream, forward, stale);
418
419 del_impl!(persistent, forward, persistent);
420 del_impl!(transient, forward, transient);
421 del_impl!(upstream, forward, stale);
422
423 #[inline]
424 fn get_all_persistents(&self) -> Option<&AHashMap<FastStr, FastStr>> {
425 match self.forward_node.as_ref() {
426 Some(node) => node.get_all_persistents(),
427 None => None,
428 }
429 }
430
431 #[inline]
432 fn get_all_transients(&self) -> Option<&AHashMap<FastStr, FastStr>> {
433 match self.forward_node.as_ref() {
434 Some(node) => node.get_all_transients(),
435 None => None,
436 }
437 }
438
439 #[inline]
440 fn get_all_upstreams(&self) -> Option<&AHashMap<FastStr, FastStr>> {
441 match self.forward_node.as_ref() {
442 Some(node) => node.get_all_stales(),
443 None => None,
444 }
445 }
446
447 #[inline]
448 fn get_all_persistents_and_transients_with_rpc_prefix(
449 &self,
450 ) -> Option<AHashMap<FastStr, FastStr>> {
451 self.get_all_persistents_and_transients_with_prefix(RpcConverter)
452 }
453
454 #[inline]
455 fn get_all_persistents_and_transients_with_http_prefix(
456 &self,
457 ) -> Option<AHashMap<FastStr, FastStr>> {
458 self.get_all_persistents_and_transients_with_prefix(HttpConverter)
459 }
460
461 #[inline]
462 fn iter_persistents_and_transients_with_rpc_prefix(
463 &self,
464 ) -> impl Iterator<Item = (FastStr, &FastStr)> {
465 self.iter_all_persistents_and_transients_with_prefix(RpcConverter)
466 }
467
468 #[inline]
469 fn iter_persistents_and_transients_with_http_prefix(
470 &self,
471 ) -> impl Iterator<Item = (FastStr, &FastStr)> {
472 self.iter_all_persistents_and_transients_with_prefix(HttpConverter)
473 }
474
475 #[inline]
476 fn strip_rpc_prefix_and_set_persistent<K: AsRef<str>, V: Into<FastStr>>(
477 &mut self,
478 key: K,
479 value: V,
480 ) {
481 let key = key.as_ref();
482 if let Some(key) = RpcConverter.remove_persistent_prefix(key) {
483 self.set_persistent(key, value);
484 }
485 }
486
487 #[inline]
488 fn strip_rpc_prefix_and_set_upstream<K: AsRef<str>, V: Into<FastStr>>(
489 &mut self,
490 key: K,
491 value: V,
492 ) {
493 let key = key.as_ref();
494 if let Some(key) = RpcConverter.remove_transient_prefix(key) {
495 self.set_upstream(key, value);
496 }
497 }
498
499 #[inline]
500 fn strip_http_prefix_and_set_persistent<K: AsRef<str>, V: Into<FastStr>>(
501 &mut self,
502 key: K,
503 value: V,
504 ) {
505 let key = key.as_ref();
506 if let Some(key) = HttpConverter.remove_persistent_prefix(key) {
507 self.set_persistent(key, value);
508 }
509 }
510
511 #[inline]
512 fn strip_http_prefix_and_set_upstream<K: AsRef<str>, V: Into<FastStr>>(
513 &mut self,
514 key: K,
515 value: V,
516 ) {
517 let key = key.as_ref();
518 if let Some(key) = HttpConverter.remove_transient_prefix(key) {
519 self.set_upstream(key, value);
520 }
521 }
522}
523
524impl backward::Backward for MetaInfo {
525 get_impl!(backward_transient, backward, transient);
526 get_impl!(backward_downstream, backward, stale);
527
528 set_impl!(backward_transient, backward, transient);
529 set_impl!(backward_downstream, backward, stale);
530
531 del_impl!(backward_transient, backward, transient);
532 del_impl!(backward_downstream, backward, stale);
533
534 fn get_all_backward_transients(&self) -> Option<&AHashMap<FastStr, FastStr>> {
535 match self.backward_node.as_ref() {
536 Some(node) => node.get_all_transients(),
537 None => None,
538 }
539 }
540
541 fn get_all_backward_downstreams(&self) -> Option<&AHashMap<FastStr, FastStr>> {
542 match self.backward_node.as_ref() {
543 Some(node) => node.get_all_stales(),
544 None => None,
545 }
546 }
547
548 fn get_all_backward_transients_with_rpc_prefix(&self) -> Option<AHashMap<FastStr, FastStr>> {
549 self.get_all_backword_transients_with_prefix(RpcConverter)
550 }
551
552 fn get_all_backward_transients_with_http_prefix(&self) -> Option<AHashMap<FastStr, FastStr>> {
553 self.get_all_backword_transients_with_prefix(HttpConverter)
554 }
555
556 fn iter_backward_transients_with_rpc_prefix(
557 &self,
558 ) -> impl Iterator<Item = (FastStr, &FastStr)> {
559 self.iter_all_backword_transients_with_prefix(RpcConverter)
560 }
561
562 fn iter_backward_transients_with_http_prefix(
563 &self,
564 ) -> impl Iterator<Item = (FastStr, &FastStr)> {
565 self.iter_all_backword_transients_with_prefix(HttpConverter)
566 }
567
568 fn strip_rpc_prefix_and_set_backward_downstream<K: AsRef<str>, V: Into<FastStr>>(
569 &mut self,
570 key: K,
571 value: V,
572 ) {
573 let key = key.as_ref();
574 if let Some(key) = RpcConverter.remove_backward_prefix(key) {
575 self.set_backward_downstream(key, value);
576 }
577 }
578
579 fn strip_http_prefix_and_set_backward_downstream<K: AsRef<str>, V: Into<FastStr>>(
580 &mut self,
581 key: K,
582 value: V,
583 ) {
584 let key = key.as_ref();
585 if let Some(key) = HttpConverter.remove_backward_prefix(key) {
586 self.set_backward_downstream(key, value);
587 }
588 }
589}
590
591impl MetaInfo {
592 #[inline]
593 fn get_all_persistents_and_transients_with_prefix<C>(
594 &self,
595 converter: C,
596 ) -> Option<AHashMap<FastStr, FastStr>>
597 where
598 C: Converter,
599 {
600 match self.forward_node.as_ref() {
601 Some(node) => {
602 let persistents = node.get_all_persistents();
603 let transients = node.get_all_transients();
604 let new_cap = persistents.map(|p| p.len()).unwrap_or(0)
605 + transients.map(|t| t.len()).unwrap_or(0);
606 if new_cap == 0 {
607 return None;
608 }
609 let mut map = AHashMap::with_capacity(new_cap);
610 if let Some(persistents) = persistents {
611 map.extend(
612 persistents
613 .iter()
614 .map(|(k, v)| (converter.add_persistent_prefix(k), v.clone())),
615 );
616 }
617 if let Some(transients) = transients {
618 map.extend(
619 transients
620 .iter()
621 .map(|(k, v)| (converter.add_transient_prefix(k), v.clone())),
622 );
623 }
624 Some(map)
625 }
626 None => None,
627 }
628 }
629
630 #[inline]
631 fn iter_all_persistents_and_transients_with_prefix<C>(
632 &self,
633 converter: C,
634 ) -> impl Iterator<Item = (FastStr, &FastStr)>
635 where
636 C: Converter + Copy + 'static,
637 {
638 self.forward_node
639 .as_ref()
640 .into_iter()
641 .flat_map(move |node| {
642 let persistents = node.get_all_persistents().into_iter().flat_map(move |p| {
643 p.into_iter()
644 .map(move |(k, v)| (converter.add_persistent_prefix(k), v))
645 });
646 let transients = node.get_all_transients().into_iter().flat_map(move |t| {
647 t.into_iter()
648 .map(move |(k, v)| (converter.add_transient_prefix(k), v))
649 });
650 persistents.chain(transients)
651 })
652 }
653
654 #[inline]
655 fn get_all_backword_transients_with_prefix<C>(
656 &self,
657 converter: C,
658 ) -> Option<AHashMap<FastStr, FastStr>>
659 where
660 C: Converter,
661 {
662 match self.backward_node.as_ref() {
663 Some(node) => {
664 if let Some(t) = node.get_all_transients() {
665 let new_cap = t.len();
666 if new_cap == 0 {
667 return None;
668 }
669 let mut map = AHashMap::with_capacity(new_cap);
670 map.extend(
671 t.iter()
672 .map(|(k, v)| (converter.add_transient_prefix(k), v.clone())),
673 );
674 Some(map)
675 } else {
676 None
677 }
678 }
679 None => None,
680 }
681 }
682
683 #[inline]
684 fn iter_all_backword_transients_with_prefix<C>(
685 &self,
686 converter: C,
687 ) -> impl Iterator<Item = (FastStr, &FastStr)>
688 where
689 C: Converter + 'static,
690 {
691 self.backward_node
692 .as_ref()
693 .into_iter()
694 .flat_map(|node| {
695 node.get_all_transients()
696 .into_iter()
697 .flat_map(|t| t.into_iter())
698 })
699 .map(move |(k, v)| (converter.add_transient_prefix(k), v))
700 }
701}
702
703impl fmt::Debug for MetaInfo {
704 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
705 f.debug_struct("MetaInfo").finish()
706 }
707}
708
709#[cfg(test)]
710mod tests {
711 use super::*;
712
713 #[test]
714 fn test_remove() {
715 let mut map = MetaInfo::new();
716
717 map.insert::<i8>(123);
718 assert!(map.get::<i8>().is_some());
719
720 map.remove::<i8>();
721 assert!(map.get::<i8>().is_none());
722
723 map.insert::<i8>(123);
724
725 let mut m2 = MetaInfo::from(Arc::new(map));
726
727 m2.remove::<i8>();
728 assert!(m2.get::<i8>().is_some());
729 }
730
731 #[test]
732 fn test_clear() {
733 let mut map = MetaInfo::new();
734
735 map.insert::<i8>(8);
736 map.insert::<i16>(16);
737 map.insert::<i32>(32);
738
739 assert!(map.contains::<i8>());
740 assert!(map.contains::<i16>());
741 assert!(map.contains::<i32>());
742
743 map.clear();
744
745 assert!(!map.contains::<i8>());
746 assert!(!map.contains::<i16>());
747 assert!(!map.contains::<i32>());
748
749 map.insert::<i8>(10);
750 assert_eq!(*map.get::<i8>().unwrap(), 10);
751 }
752
753 #[test]
754 fn test_integers() {
755 let mut map = MetaInfo::new();
756
757 map.insert::<i8>(8);
758 map.insert::<i16>(16);
759 map.insert::<i32>(32);
760 map.insert::<i64>(64);
761 map.insert::<i128>(128);
762 map.insert::<u8>(8);
763 map.insert::<u16>(16);
764 map.insert::<u32>(32);
765 map.insert::<u64>(64);
766 map.insert::<u128>(128);
767 assert!(map.get::<i8>().is_some());
768 assert!(map.get::<i16>().is_some());
769 assert!(map.get::<i32>().is_some());
770 assert!(map.get::<i64>().is_some());
771 assert!(map.get::<i128>().is_some());
772 assert!(map.get::<u8>().is_some());
773 assert!(map.get::<u16>().is_some());
774 assert!(map.get::<u32>().is_some());
775 assert!(map.get::<u64>().is_some());
776 assert!(map.get::<u128>().is_some());
777
778 let m2 = MetaInfo::from(Arc::new(map));
779 assert!(m2.get::<i8>().is_some());
780 assert!(m2.get::<i16>().is_some());
781 assert!(m2.get::<i32>().is_some());
782 assert!(m2.get::<i64>().is_some());
783 assert!(m2.get::<i128>().is_some());
784 assert!(m2.get::<u8>().is_some());
785 assert!(m2.get::<u16>().is_some());
786 assert!(m2.get::<u32>().is_some());
787 assert!(m2.get::<u64>().is_some());
788 assert!(m2.get::<u128>().is_some());
789 }
790
791 #[test]
792 fn test_composition() {
793 struct Magi<T>(pub T);
794
795 struct Madoka {
796 pub god: bool,
797 }
798
799 struct Homura {
800 pub attempts: usize,
801 }
802
803 struct Mami {
804 pub guns: usize,
805 }
806
807 let mut map = MetaInfo::new();
808
809 map.insert(Magi(Madoka { god: false }));
810 map.insert(Magi(Homura { attempts: 0 }));
811 map.insert(Magi(Mami { guns: 999 }));
812
813 assert!(!map.get::<Magi<Madoka>>().unwrap().0.god);
814 assert_eq!(0, map.get::<Magi<Homura>>().unwrap().0.attempts);
815 assert_eq!(999, map.get::<Magi<Mami>>().unwrap().0.guns);
816 }
817
818 #[test]
819 fn test_metainfo() {
820 #[derive(Debug, PartialEq)]
821 struct MyType(i32);
822
823 let mut metainfo = MetaInfo::new();
824
825 metainfo.insert(5i32);
826 metainfo.insert(MyType(10));
827
828 assert_eq!(metainfo.get(), Some(&5i32));
829
830 assert_eq!(metainfo.remove::<i32>(), Some(5i32));
831 assert!(metainfo.get::<i32>().is_none());
832
833 assert_eq!(metainfo.get::<bool>(), None);
834 assert_eq!(metainfo.get(), Some(&MyType(10)));
835 }
836
837 #[test]
838 fn test_extend() {
839 #[derive(Debug, PartialEq)]
840 struct MyType(i32);
841
842 let mut metainfo = MetaInfo::new();
843
844 metainfo.insert(5i32);
845 metainfo.insert(MyType(10));
846
847 let mut other = MetaInfo::new();
848
849 other.insert(15i32);
850 other.insert(20u8);
851
852 metainfo.extend(other);
853
854 assert_eq!(metainfo.get(), Some(&15i32));
855
856 assert_eq!(metainfo.remove::<i32>(), Some(15i32));
857 assert!(metainfo.get::<i32>().is_none());
858
859 assert_eq!(metainfo.get::<bool>(), None);
860 assert_eq!(metainfo.get(), Some(&MyType(10)));
861
862 assert_eq!(metainfo.get(), Some(&20u8));
863 }
864
865 #[test]
866 fn rpc_forward_test() {
867 let mut metainfo = MetaInfo::new();
868 metainfo.strip_rpc_prefix_and_set_persistent("RPC_PERSIST_TEST_KEY", "PERSIST");
869 metainfo.strip_rpc_prefix_and_set_upstream("RPC_TRANSIT_TEST_KEY", "TRANSIT");
870 assert_eq!(metainfo.get_persistent("TEST_KEY").unwrap(), "PERSIST");
871 assert_eq!(metainfo.get_upstream("TEST_KEY").unwrap(), "TRANSIT");
872 let map = metainfo
873 .get_all_persistents_and_transients_with_rpc_prefix()
874 .unwrap();
875 assert_eq!(map.get("RPC_PERSIST_TEST_KEY").unwrap(), "PERSIST");
876 }
879
880 #[test]
881 fn http_forward_test() {
882 let mut metainfo = MetaInfo::new();
883 metainfo.strip_http_prefix_and_set_persistent("rpc-persist-test-key", "persist");
884 metainfo.strip_http_prefix_and_set_upstream("rpc-transit-test-key", "transit");
885 assert_eq!(metainfo.get_persistent("TEST_KEY").unwrap(), "persist");
886 assert_eq!(metainfo.get_upstream("TEST_KEY").unwrap(), "transit");
887 let map = metainfo
888 .get_all_persistents_and_transients_with_http_prefix()
889 .unwrap();
890 assert_eq!(map.get("rpc-persist-test-key").unwrap(), "persist");
891 let iter = metainfo.iter_all_persistents_and_transients_with_prefix(HttpConverter);
892 assert_eq!(iter.count(), 1);
893 metainfo.set_persistent("test_key2", "test_value2");
894 let iter = metainfo.iter_all_persistents_and_transients_with_prefix(HttpConverter);
895 assert_eq!(iter.count(), 2);
896 }
899}