base_traits/traits/
len.rs

1// src/traits/len.rs : `Len`
2
3/// Trait defining instance method `len() : usize` that indicates
4/// whether the implementing type instance is logically empty.
5///
6/// # Additional Implementations on Foreign Types
7///
8/// ## Built-in Types
9///
10/// If the feature `"implement-Len-for-built_ins"`
11/// is defined (as it is by `"default"`), then this is also implemented
12/// for the following types:
13/// - [`str`];
14/// - `[T; N]`;
15/// - `[T]`;
16///
17/// ## Standard Collection Types
18///
19/// If the feature `"implement-Len-for-standard_collection_types"`
20/// is defined (as it is by `"default"`), then this is also implemented
21/// for the following types:
22/// - [`std::collections::BTreeMap`];
23/// - [`std::collections::BTreeSet`];
24/// - [`std::collections::BinaryHeap`];
25/// - [`std::collections::HashMap`];
26/// - [`std::collections::HashSet`];
27/// - [`std::collections::LinkedList`];
28/// - [`String`];
29/// - [`Vec`];
30/// - [`std::collections::VecDeque`];
31///
32/// ## Standard FFI Types
33///
34/// If the feature `"implement-Len-for-standard_ffi_types"`
35/// is defined (as it is by `"default"`), then this is also implemented
36/// for the following types:
37/// - [`std::ffi::CStr`];
38/// - [`std::ffi::CString`];
39///
40/// ## Standard Path Types
41///
42/// If the feature `"implement-Len-for-standard_path_types"`
43/// is defined (as it is by `"default"`), then this is also implemented
44/// for the following types:
45/// - [`std::path::Path`];
46/// - [`std::path::PathBuf`];
47///
48/// ## Standard Process Types
49///
50/// If the feature `"implement-Len-for-standard_process_types"`
51/// is defined (as it is by `"default"`), then this is also implemented
52/// for the following types:
53/// - [`std::process::CommandArgs`];
54/// - [`std::process::CommandEnvs`];
55#[allow(clippy::len_without_is_empty)]
56pub trait Len {
57    fn len(&self) -> usize;
58}
59
60
61#[cfg(all(not(test), not(feature = "nostd")))]
62impl<T : Len + ?Sized> Len for Box<T> {
63    fn len(&self) -> usize {
64        (**self).len()
65    }
66}
67
68#[cfg(all(not(test), not(feature = "nostd")))]
69impl<T : Len + ?Sized> Len for std::rc::Rc<T> {
70    fn len(&self) -> usize {
71        (**self).len()
72    }
73}
74
75
76#[cfg(feature = "implement-Len-for-built_ins")]
77mod impl_for_built_ins {
78
79    mod isolate_ {
80        #![allow(non_snake_case)]
81
82
83        #[inline]
84        pub(super) fn get_len_str_(s : &str) -> usize {
85            s.len()
86        }
87
88        #[inline]
89        pub(super) fn get_len_Slice_<T>(s : &[T]) -> usize {
90            s.len()
91        }
92    }
93
94
95    // str
96
97    impl super::Len for str {
98        fn len(&self) -> usize {
99            isolate_::get_len_str_(self)
100        }
101    }
102
103    impl super::Len for &str {
104        fn len(&self) -> usize {
105            isolate_::get_len_str_(self)
106        }
107    }
108
109    // Array
110
111    impl<T, const N: usize> super::Len for [T; N] {
112        fn len(&self) -> usize {
113            N
114        }
115    }
116
117    impl<T, const N: usize> super::Len for &[T; N] {
118        fn len(&self) -> usize {
119            N
120        }
121    }
122
123    // Slice
124
125    impl<T> super::Len for [T] {
126        fn len(&self) -> usize {
127            isolate_::get_len_Slice_(self)
128        }
129    }
130
131    impl<T> super::Len for &[T] {
132        fn len(&self) -> usize {
133            isolate_::get_len_Slice_(self)
134        }
135    }
136}
137
138
139#[cfg(all(not(feature = "nostd"), feature = "implement-Len-for-standard_collection_types"))]
140mod impl_for_std_coll_types {
141    use std::collections as std_collections;
142
143
144    mod isolate_ {
145        #![allow(non_snake_case)]
146
147        use std::collections as std_collections;
148
149
150        #[inline]
151        pub(super) fn get_len_BTreeMap_<K, V>(coll : &std_collections::BTreeMap<K, V>) -> usize {
152            coll.len()
153        }
154
155        #[inline]
156        pub(super) fn get_len_BTreeSet_<T>(coll : &std_collections::BTreeSet<T>) -> usize {
157            coll.len()
158        }
159
160        #[inline]
161        pub(super) fn get_len_BinaryHeap_<T>(coll : &std_collections::BinaryHeap<T>) -> usize {
162            coll.len()
163        }
164
165        #[inline]
166        pub(super) fn get_len_HashMap_<K, V>(coll : &std_collections::HashMap<K, V>) -> usize {
167            coll.len()
168        }
169
170        #[inline]
171        pub(super) fn get_len_HashSet_<T>(coll : &std_collections::HashSet<T>) -> usize {
172            coll.len()
173        }
174
175        #[inline]
176        pub(super) fn get_len_LinkedList_<T>(coll : &std_collections::LinkedList<T>) -> usize {
177            coll.len()
178        }
179
180        // NOTE: parameter type is `&str`, not `&String`
181        #[inline]
182        pub(super) fn get_len_String_(s : &str) -> usize {
183            s.len()
184        }
185
186        #[inline]
187        pub(super) fn get_len_Vec_<T>(coll : &[T]) -> usize {
188            coll.len()
189        }
190
191        #[inline]
192        pub(super) fn get_len_VecDeque_<T>(coll : &std_collections::VecDeque<T>) -> usize {
193            coll.len()
194        }
195    }
196
197
198    // BTreeMap<>
199
200    impl<K, V> super::Len for std_collections::BTreeMap<K, V> {
201        fn len(&self) -> usize {
202            isolate_::get_len_BTreeMap_(self)
203        }
204    }
205
206    // BTreeSet<>
207
208    impl<T> super::Len for std_collections::BTreeSet<T> {
209        fn len(&self) -> usize {
210            isolate_::get_len_BTreeSet_(self)
211        }
212    }
213
214    // BinaryHeap<>
215
216    impl<T> super::Len for std_collections::BinaryHeap<T> {
217        fn len(&self) -> usize {
218            isolate_::get_len_BinaryHeap_(self)
219        }
220    }
221
222    // HashMap<>
223
224    impl<K, V> super::Len for std_collections::HashMap<K, V> {
225        fn len(&self) -> usize {
226            isolate_::get_len_HashMap_(self)
227        }
228    }
229
230    // HashSet<>
231
232    impl<T> super::Len for std_collections::HashSet<T> {
233        fn len(&self) -> usize {
234            isolate_::get_len_HashSet_(self)
235        }
236    }
237
238    // LinkedList<>
239
240    impl<T> super::Len for std_collections::LinkedList<T> {
241        fn len(&self) -> usize {
242            isolate_::get_len_LinkedList_(self)
243        }
244    }
245
246    // String
247
248    impl super::Len for String {
249        fn len(&self) -> usize {
250            isolate_::get_len_String_(self)
251        }
252    }
253
254    // Vec<>
255
256    impl<T> super::Len for Vec<T> {
257        fn len(&self) -> usize {
258            isolate_::get_len_Vec_(self)
259        }
260    }
261
262    // VecDeque<>
263
264    impl<T> super::Len for std_collections::VecDeque<T> {
265        fn len(&self) -> usize {
266            isolate_::get_len_VecDeque_(self)
267        }
268    }
269}
270
271
272#[cfg(all(not(feature = "nostd"), feature = "implement-Len-for-standard_ffi_types"))]
273mod impl_for_std_ffi_types {
274    #![allow(non_snake_case)]
275
276    use std::ffi as std_ffi;
277
278
279    mod isolate_ {
280        #![allow(non_snake_case)]
281
282        use std::ffi as std_ffi;
283
284
285        #[inline]
286        pub(super) fn get_len_CStr_(cstr : &std_ffi::CStr) -> usize {
287            cstr.count_bytes()
288        }
289
290        #[inline]
291        pub(super) fn get_len_CString_(cstring : &std_ffi::CString) -> usize {
292            cstring.count_bytes()
293        }
294    }
295
296
297    // CStr
298
299    impl super::Len for std_ffi::CStr {
300        fn len(&self) -> usize {
301            isolate_::get_len_CStr_(self)
302        }
303    }
304
305    impl super::Len for &std_ffi::CStr {
306        fn len(&self) -> usize {
307            isolate_::get_len_CStr_(self)
308        }
309    }
310
311    // CString
312
313    impl super::Len for std_ffi::CString {
314        fn len(&self) -> usize {
315            isolate_::get_len_CString_(self)
316        }
317    }
318}
319
320
321#[cfg(all(not(feature = "nostd"), feature = "implement-Len-for-standard_path_types"))]
322mod impl_for_std_path_types {
323    use std::path as std_path;
324
325
326    // Path
327
328    impl super::Len for &std_path::Path {
329        fn len(&self) -> usize {
330            self.as_os_str().len()
331        }
332    }
333
334    // PathBuf
335
336    impl super::Len for std_path::PathBuf {
337        fn len(&self) -> usize {
338            self.as_os_str().len()
339        }
340    }
341
342    impl super::Len for &std_path::PathBuf {
343        fn len(&self) -> usize {
344            self.as_os_str().len()
345        }
346    }
347}
348
349
350#[cfg(all(not(feature = "nostd"), feature = "implement-Len-for-standard_process_types"))]
351mod impl_for_std_process_types {
352    #![allow(non_snake_case)]
353
354    use std::process as std_process;
355
356
357    mod isolate_ {
358        #![allow(non_snake_case)]
359
360        use std::process as std_process;
361
362
363        #[inline]
364        pub(super) fn get_len_CommandArgs_<'a>(ca : &std_process::CommandArgs<'a>) -> usize {
365            ca.len()
366        }
367
368        #[inline]
369        pub(super) fn get_len_CommandEnvs_<'a>(ce : &std_process::CommandEnvs<'a>) -> usize {
370            ce.len()
371        }
372    }
373
374
375    // CommandArgs<'>
376
377    impl<'a> super::Len for &std_process::CommandArgs<'a> {
378        fn len(&self) -> usize {
379            isolate_::get_len_CommandArgs_(self)
380        }
381    }
382
383    // CommandEnvs<'>
384
385    impl<'a> super::Len for &std_process::CommandEnvs<'a> {
386        fn len(&self) -> usize {
387            isolate_::get_len_CommandEnvs_(self)
388        }
389    }
390}
391
392
393#[cfg(test)]
394mod tests {
395    #![allow(non_snake_case)]
396
397    use super::Len;
398
399    #[cfg(feature = "implement-Len-for-standard_collection_types")]
400    use std::rc::Rc;
401
402
403    #[allow(unused)]
404    fn as_Len<T : Len>(t : &T) -> &impl Len {
405        t
406    }
407
408
409    mod TEST_CUSTOM_TYPE {
410        #![allow(non_snake_case)]
411
412        use super::*;
413
414
415        #[derive(Debug)]
416        struct CustomType {
417            num_elements : usize,
418        }
419
420        impl Len for CustomType {
421            fn len(&self) -> usize {
422                self.num_elements
423            }
424        }
425
426
427        #[test]
428        fn TEST_WHEN_ZERO_ELEMENTS() {
429            let ct = CustomType { num_elements : 0 };
430
431            assert_eq!(0, ct.len());
432
433            let ct = &ct;
434
435            assert_eq!(0, ct.len());
436        }
437
438        #[test]
439        fn TEST_WHEN_HAVE_ELEMENTS() {
440            let ct = CustomType { num_elements : 1 };
441
442            assert_ne!(0, ct.len());
443
444            let ct = &ct;
445
446            assert_ne!(0, ct.len());
447        }
448    }
449
450
451    #[cfg(feature = "implement-Len-for-built_ins")]
452    mod TEST_BUILTIN_TYPES {
453        #![allow(non_snake_case)]
454
455        use super::*;
456
457
458        mod TEST_str {
459            #![allow(non_snake_case)]
460
461            use super::*;
462
463
464            #[test]
465            fn TEST_EMPTY() {
466                let s = "";
467
468                assert_eq!(0, s.len());
469
470                let ie = as_Len(&s);
471
472                assert_eq!(0, ie.len());
473            }
474
475            #[test]
476            fn TEST_NONEMPTY() {
477                let s = "abc";
478
479                assert_ne!(0, s.len());
480
481                let ie = as_Len(&s);
482
483                assert_ne!(0, ie.len());
484            }
485        }
486
487
488        mod TEST_Array {
489            #![allow(non_snake_case)]
490
491            use super::*;
492
493
494            #[test]
495            fn TEST_EMPTY() {
496                let ar : [i64; 0] = [];
497
498                assert_eq!(0, ar.len());
499
500                let ie = as_Len(&ar);
501
502                assert_eq!(0, ie.len());
503            }
504
505            #[test]
506            fn TEST_NONEMPTY() {
507                let ar : [i64; 1] = [ 0 ];
508
509                assert_ne!(0, ar.len());
510
511                let ie = as_Len(&ar);
512
513                assert_ne!(0, ie.len());
514            }
515        }
516
517
518        mod TEST_Slice {
519            #![allow(non_snake_case)]
520
521            use super::*;
522
523
524            #[test]
525            fn TEST_EMPTY() {
526                let ar : &[i64; 0] = &[];
527
528                assert_eq!(0, ar.len());
529
530                let ie = as_Len(&ar);
531
532                assert_eq!(0, ie.len());
533            }
534
535            #[test]
536            fn TEST_NONEMPTY() {
537                let ar = &[0];
538
539                assert_ne!(0, ar.len());
540
541                let ie = as_Len(&ar);
542
543                assert_ne!(0, ie.len());
544            }
545        }
546    }
547
548
549    #[cfg(feature = "implement-Len-for-standard_collection_types")]
550    mod TEST_STANDARD_TYPES {
551        #![allow(non_snake_case)]
552
553        use super::*;
554
555        use std::collections::{
556            BTreeMap,
557            BTreeSet,
558            BinaryHeap,
559            HashMap,
560            HashSet,
561            LinkedList,
562            VecDeque,
563        };
564
565
566        mod TEST_BTreeMapTU {
567            #![allow(non_snake_case)]
568
569            use super::*;
570
571
572            #[test]
573            fn TEST_EMPTY() {
574                let v : BTreeMap<i32, i32> = Default::default();
575
576                assert_eq!(0, v.len());
577
578                let ie = as_Len(&v);
579
580                assert_eq!(0, ie.len());
581            }
582
583            #[test]
584            fn TEST_NONEMPTY() {
585                let v = BTreeMap::from_iter(vec![ (0, 0) ]);
586
587                assert_ne!(0, v.len());
588
589                let ie = as_Len(&v);
590
591                assert_ne!(0, ie.len());
592            }
593        }
594
595
596        mod TEST_BTreeSetT {
597            #![allow(non_snake_case)]
598
599            use super::*;
600
601
602            #[test]
603            fn TEST_EMPTY() {
604                let v : BTreeSet<i32> = Default::default();
605
606                assert_eq!(0, v.len());
607
608                let ie = as_Len(&v);
609
610                assert_eq!(0, ie.len());
611            }
612
613            #[test]
614            fn TEST_NONEMPTY() {
615                let v = BTreeSet::from_iter(vec![ 0 ]);
616
617                assert_ne!(0, v.len());
618
619                let ie = as_Len(&v);
620
621                assert_ne!(0, ie.len());
622            }
623        }
624
625
626        mod TEST_BinaryHeapT {
627            #![allow(non_snake_case)]
628
629            use super::*;
630
631
632            #[test]
633            fn TEST_EMPTY() {
634                let v : BinaryHeap<i32> = Default::default();
635
636                assert_eq!(0, v.len());
637
638                let ie = as_Len(&v);
639
640                assert_eq!(0, ie.len());
641            }
642
643            #[test]
644            fn TEST_NONEMPTY() {
645                let v = BinaryHeap::from_iter(vec![ 0 ]);
646
647                assert_ne!(0, v.len());
648
649                let ie = as_Len(&v);
650
651                assert_ne!(0, ie.len());
652            }
653        }
654
655
656        mod TEST_HashMapTU {
657            #![allow(non_snake_case)]
658
659            use super::*;
660
661
662            #[test]
663            fn TEST_EMPTY() {
664                let v : HashMap<i32, i32> = Default::default();
665
666                assert_eq!(0, v.len());
667
668                let ie = as_Len(&v);
669
670                assert_eq!(0, ie.len());
671            }
672
673            #[test]
674            fn TEST_NONEMPTY() {
675                let v = HashMap::from_iter(vec![ (0, 0) ]);
676
677                assert_ne!(0, v.len());
678
679                let ie = as_Len(&v);
680
681                assert_ne!(0, ie.len());
682            }
683        }
684
685
686        mod TEST_HashSetT {
687            #![allow(non_snake_case)]
688
689            use super::*;
690
691
692            #[test]
693            fn TEST_EMPTY() {
694                let v : HashSet<i32> = Default::default();
695
696                assert_eq!(0, v.len());
697
698                let ie = as_Len(&v);
699
700                assert_eq!(0, ie.len());
701            }
702
703            #[test]
704            fn TEST_NONEMPTY() {
705                let v = HashSet::from_iter(vec![ 0 ]);
706
707                assert_ne!(0, v.len());
708
709                let ie = as_Len(&v);
710
711                assert_ne!(0, ie.len());
712            }
713        }
714
715
716        mod TEST_LinkedListT {
717            #![allow(non_snake_case)]
718
719            use super::*;
720
721
722            #[test]
723            fn TEST_EMPTY() {
724                let v : LinkedList<i32> = Default::default();
725
726                assert_eq!(0, v.len());
727
728                let ie = as_Len(&v);
729
730                assert_eq!(0, ie.len());
731            }
732
733            #[test]
734            fn TEST_NONEMPTY() {
735                let v = LinkedList::from_iter(vec![ 0 ]);
736
737                assert_ne!(0, v.len());
738
739                let ie = as_Len(&v);
740
741                assert_ne!(0, ie.len());
742            }
743        }
744
745
746        mod TEST_String {
747            #![allow(non_snake_case)]
748
749            use super::*;
750
751
752            #[test]
753            fn TEST_EMPTY() {
754                let s : String = "".into();
755
756                assert_eq!(0, s.len());
757
758                let ie = as_Len(&s);
759
760                assert_eq!(0, ie.len());
761            }
762
763            #[test]
764            fn TEST_NONEMPTY() {
765                let s : String = "abc".into();
766
767                assert_ne!(0, s.len());
768
769                let ie = as_Len(&s);
770
771                assert_ne!(0, ie.len());
772            }
773        }
774
775
776        mod TEST_String_IN_Box {
777            #![allow(non_snake_case)]
778
779            use super::*;
780
781
782            #[test]
783            fn TEST_EMPTY() {
784                let s : Box<String> = Box::new("".into());
785
786                assert_eq!(0, s.len());
787
788                let ie = as_Len(&s);
789
790                assert_eq!(0, ie.len());
791            }
792
793            #[test]
794            fn TEST_NONEMPTY() {
795                let s : Box<String> = Box::new("abc".into());
796
797                assert_ne!(0, s.len());
798
799                let ie = as_Len(&s);
800
801                assert_ne!(0, ie.len());
802            }
803        }
804
805
806        mod TEST_String_IN_Rc {
807            #![allow(non_snake_case)]
808
809            use super::*;
810
811
812            #[test]
813            fn TEST_EMPTY() {
814                let s : Rc<String> = Rc::new("".into());
815
816                assert_eq!(0, s.len());
817
818                let ie = as_Len(&s);
819
820                assert_eq!(0, ie.len());
821            }
822
823            #[test]
824            fn TEST_NONEMPTY() {
825                let s : Rc<String> = Rc::new("abc".into());
826
827                assert_ne!(0, s.len());
828
829                let ie = as_Len(&s);
830
831                assert_ne!(0, ie.len());
832            }
833        }
834
835
836        mod TEST_VecT {
837            #![allow(non_snake_case)]
838
839            use super::*;
840
841
842            #[test]
843            fn TEST_EMPTY() {
844                let v : Vec<i32> = Default::default();
845
846                assert_eq!(0, v.len());
847
848                let ie = as_Len(&v);
849
850                assert_eq!(0, ie.len());
851            }
852
853            #[test]
854            fn TEST_NONEMPTY() {
855                let v : Vec<i32> = vec![ 0 ];
856
857                assert_ne!(0, v.len());
858
859                let ie = as_Len(&v);
860
861                assert_ne!(0, ie.len());
862            }
863        }
864
865
866        mod TEST_VecDequeT {
867            #![allow(non_snake_case)]
868
869            use super::*;
870
871
872            #[test]
873            fn TEST_EMPTY() {
874                let v : VecDeque<i32> = Default::default();
875
876                assert_eq!(0, v.len());
877
878                let ie = as_Len(&v);
879
880                assert_eq!(0, ie.len());
881            }
882
883            #[test]
884            fn TEST_NONEMPTY() {
885                let v = VecDeque::from_iter(vec![ 0 ]);
886
887                assert_ne!(0, v.len());
888
889                let ie = as_Len(&v);
890
891                assert_ne!(0, ie.len());
892            }
893        }
894    }
895
896
897    #[cfg(feature = "implement-Len-for-standard_ffi_types")]
898    mod TEST_FFI_TYPES {
899        #![allow(non_snake_case)]
900
901        use super::*;
902
903        use std::ffi::{
904            CStr,
905            CString,
906        };
907
908
909        mod TEST_CStr {
910            #![allow(non_snake_case)]
911
912            use super::*;
913
914
915            #[test]
916            fn TEST_EMPTY() {
917                let s : &CStr = &CString::new("").unwrap();
918
919                assert_eq!(0, s.len());
920
921                let ie = as_Len(&s);
922
923                assert_eq!(0, ie.len());
924            }
925
926            #[test]
927            fn TEST_NONEMPTY() {
928                let s : &CStr = &CString::new("abc").unwrap();
929
930                assert_ne!(0, s.len());
931
932                let ie = as_Len(&s);
933
934                assert_ne!(0, ie.len());
935            }
936        }
937
938
939        mod TEST_CString {
940            #![allow(non_snake_case)]
941
942            use super::*;
943
944
945            #[test]
946            fn TEST_EMPTY() {
947                let s : CString = CString::new("").unwrap();
948
949                assert_eq!(0, s.len());
950
951                let ie = as_Len(&s);
952
953                assert_eq!(0, ie.len());
954            }
955
956            #[test]
957            fn TEST_NONEMPTY() {
958                let s : CString = CString::new("abc").unwrap();
959
960                assert_ne!(0, s.len());
961
962                let ie = as_Len(&s);
963
964                assert_ne!(0, ie.len());
965            }
966        }
967    }
968
969
970    #[cfg(feature = "implement-Len-for-standard_path_types")]
971    mod TEST_PATH_TYPES {
972        #![allow(non_snake_case)]
973
974        use super::*;
975
976        use std::path::{
977            Path,
978            PathBuf,
979        };
980
981
982        mod TEST_Path {
983            #![allow(non_snake_case)]
984
985            use super::*;
986
987
988            #[test]
989            fn TEST_EMPTY() {
990                let p = Path::new("");
991
992                assert_eq!(0, p.len());
993
994                let ie = as_Len(&p);
995
996                assert_eq!(0, ie.len());
997            }
998
999            #[test]
1000            fn TEST_NOTEMPTY() {
1001                let p = Path::new("./foo/bar.txt");
1002
1003                assert_ne!(0, p.len());
1004
1005                let ie = as_Len(&p);
1006
1007                assert_ne!(0, ie.len());
1008            }
1009        }
1010
1011
1012        mod TEST_PathBuf {
1013            #![allow(non_snake_case)]
1014
1015            use super::*;
1016
1017
1018            #[test]
1019            fn TEST_EMPTY() {
1020                let p = PathBuf::new();
1021
1022                assert_eq!(0, p.len());
1023
1024                let ie = as_Len(&p);
1025
1026                assert_eq!(0, ie.len());
1027            }
1028
1029            #[test]
1030            fn TEST_NOTEMPTY() {
1031                let mut p = PathBuf::new();
1032
1033                p.push("./foo/bar.txt");
1034
1035                assert_ne!(0, p.len());
1036
1037                let ie = as_Len(&p);
1038
1039                assert_ne!(0, ie.len());
1040            }
1041        }
1042    }
1043
1044
1045    #[cfg(feature = "implement-Len-for-standard_process_types")]
1046    mod TEST_PROCESS_TYPES {
1047        #![allow(non_snake_case)]
1048
1049    }
1050}
1051
1052
1053// ///////////////////////////// end of file //////////////////////////// //
1054