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