1#[macro_export]
50macro_rules! impl_dependency {
51 ($type:ty {
52 name: $name:ident,
53 name_range: $name_range:ident,
54 version: $version:ident,
55 version_range: $version_range:ident $(,)?
56 }) => {
57 impl $crate::ecosystem::Dependency for $type {
58 fn name(&self) -> &$crate::PackageName {
59 &self.$name
60 }
61
62 fn name_range(&self) -> $crate::position::Range {
63 self.$name_range
64 }
65
66 fn version_requirement(&self) -> Option<&$crate::VersionReq> {
67 self.$version.as_ref()
68 }
69
70 fn version_range(&self) -> Option<$crate::position::Range> {
71 self.$version_range
72 }
73
74 fn source(&self) -> $crate::parser::DependencySource {
75 $crate::parser::DependencySource::Registry
76 }
77
78 fn as_any(&self) -> &dyn ::std::any::Any {
79 self
80 }
81 }
82 };
83 ($type:ty {
84 name: $name:ident,
85 name_range: $name_range:ident,
86 version: $version:ident,
87 version_range: $version_range:ident,
88 source: $source:ident $(,)?
89 }) => {
90 impl $crate::ecosystem::Dependency for $type {
91 fn name(&self) -> &$crate::PackageName {
92 &self.$name
93 }
94
95 fn name_range(&self) -> $crate::position::Range {
96 self.$name_range
97 }
98
99 fn version_requirement(&self) -> Option<&$crate::VersionReq> {
100 self.$version.as_ref()
101 }
102
103 fn version_range(&self) -> Option<$crate::position::Range> {
104 self.$version_range
105 }
106
107 fn source(&self) -> $crate::parser::DependencySource {
108 self.$source.clone()
109 }
110
111 fn as_any(&self) -> &dyn ::std::any::Any {
112 self
113 }
114 }
115 };
116 ($type:ty {
117 name: $name:ident,
118 name_range: $name_range:ident,
119 version: $version:ident,
120 version_range: $version_range:ident,
121 source: $source:ident,
122 version_literal: $version_literal:ident $(,)?
123 }) => {
124 impl $crate::ecosystem::Dependency for $type {
125 fn name(&self) -> &$crate::PackageName {
126 &self.$name
127 }
128
129 fn name_range(&self) -> $crate::position::Range {
130 self.$name_range
131 }
132
133 fn version_requirement(&self) -> Option<&$crate::VersionReq> {
134 self.$version.as_ref()
135 }
136
137 fn version_range(&self) -> Option<$crate::position::Range> {
138 self.$version_range
139 }
140
141 fn source(&self) -> $crate::parser::DependencySource {
142 self.$source.clone()
143 }
144
145 fn version_literal(&self) -> Option<&str> {
146 self.$version_literal.as_deref()
147 }
148
149 fn as_any(&self) -> &dyn ::std::any::Any {
150 self
151 }
152 }
153 };
154}
155
156#[macro_export]
234macro_rules! impl_version {
235 ($type:ty {
236 version: $version:ident,
237 status: $status:expr $(,)?
238 }) => {
239 impl $crate::registry::Version for $type {
240 fn version_string(&self) -> &$crate::ConcreteVersion {
241 &self.$version
242 }
243
244 fn removal_status(&self) -> $crate::registry::RemovalStatus {
245 ($status)(self)
246 }
247
248 fn as_any(&self) -> &dyn ::std::any::Any {
249 self
250 }
251 }
252 };
253 ($type:ty {
254 version: $version:ident,
255 status: $status:expr,
256 published_at: $published_at:ident $(,)?
257 }) => {
258 impl $crate::registry::Version for $type {
259 fn version_string(&self) -> &$crate::ConcreteVersion {
260 &self.$version
261 }
262
263 fn removal_status(&self) -> $crate::registry::RemovalStatus {
264 ($status)(self)
265 }
266
267 fn published_at(&self) -> Option<$crate::freshness::PublishTime> {
268 self.$published_at
269 }
270
271 fn as_any(&self) -> &dyn ::std::any::Any {
272 self
273 }
274 }
275 };
276 ($type:ty {
277 version: $version:ident,
278 status: $status:expr,
279 prerelease: $prerelease:expr $(,)?
280 }) => {
281 impl $crate::registry::Version for $type {
282 fn version_string(&self) -> &$crate::ConcreteVersion {
283 &self.$version
284 }
285
286 fn removal_status(&self) -> $crate::registry::RemovalStatus {
287 ($status)(self)
288 }
289
290 fn is_prerelease(&self) -> bool {
291 ($prerelease)(self)
292 }
293
294 fn as_any(&self) -> &dyn ::std::any::Any {
295 self
296 }
297 }
298 };
299 ($type:ty {
300 version: $version:ident,
301 status: $status:expr,
302 published_at: $published_at:ident,
303 prerelease: $prerelease:expr $(,)?
304 }) => {
305 impl $crate::registry::Version for $type {
306 fn version_string(&self) -> &$crate::ConcreteVersion {
307 &self.$version
308 }
309
310 fn removal_status(&self) -> $crate::registry::RemovalStatus {
311 ($status)(self)
312 }
313
314 fn published_at(&self) -> Option<$crate::freshness::PublishTime> {
315 self.$published_at
316 }
317
318 fn is_prerelease(&self) -> bool {
319 ($prerelease)(self)
320 }
321
322 fn as_any(&self) -> &dyn ::std::any::Any {
323 self
324 }
325 }
326 };
327 ($type:ty {
328 version: $version:ident,
329 status: $status:expr,
330 published_at: $published_at:ident,
331 prerelease: $prerelease:expr,
332 deprecation: $deprecation:expr $(,)?
333 }) => {
334 impl $crate::registry::Version for $type {
335 fn version_string(&self) -> &$crate::ConcreteVersion {
336 &self.$version
337 }
338
339 fn removal_status(&self) -> $crate::registry::RemovalStatus {
340 ($status)(self)
341 }
342
343 fn published_at(&self) -> Option<$crate::freshness::PublishTime> {
344 self.$published_at
345 }
346
347 fn is_prerelease(&self) -> bool {
348 ($prerelease)(self)
349 }
350
351 fn deprecation(&self) -> Option<&$crate::registry::Deprecation> {
352 let f: fn(&$type) -> Option<&$crate::registry::Deprecation> = $deprecation;
358 f(self)
359 }
360
361 fn as_any(&self) -> &dyn ::std::any::Any {
362 self
363 }
364 }
365 };
366 ($type:ty {
367 version: $version:ident,
368 status: $status:expr,
369 published_at: $published_at:ident,
370 prerelease: $prerelease:expr,
371 deprecation: $deprecation:expr,
372 license: $license:ident $(,)?
373 }) => {
374 impl $crate::registry::Version for $type {
375 fn version_string(&self) -> &$crate::ConcreteVersion {
376 &self.$version
377 }
378
379 fn removal_status(&self) -> $crate::registry::RemovalStatus {
380 ($status)(self)
381 }
382
383 fn published_at(&self) -> Option<$crate::freshness::PublishTime> {
384 self.$published_at
385 }
386
387 fn is_prerelease(&self) -> bool {
388 ($prerelease)(self)
389 }
390
391 fn deprecation(&self) -> Option<&$crate::registry::Deprecation> {
392 let f: fn(&$type) -> Option<&$crate::registry::Deprecation> = $deprecation;
393 f(self)
394 }
395
396 fn license(&self) -> &[String] {
397 &self.$license
398 }
399
400 fn as_any(&self) -> &dyn ::std::any::Any {
401 self
402 }
403 }
404 };
405}
406
407#[macro_export]
440macro_rules! impl_metadata {
441 ($type:ty {
442 name: $name:ident,
443 description: $description:ident,
444 repository: $repository:ident,
445 documentation: $documentation:ident,
446 latest_version: $latest_version:ident $(,)?
447 }) => {
448 impl $crate::registry::Metadata for $type {
449 fn name(&self) -> &$crate::PackageName {
450 &self.$name
451 }
452
453 fn description(&self) -> Option<&str> {
454 self.$description.as_deref()
455 }
456
457 fn repository(&self) -> Option<&str> {
458 self.$repository.as_deref()
459 }
460
461 fn documentation(&self) -> Option<&str> {
462 self.$documentation.as_deref()
463 }
464
465 fn latest_version(&self) -> &$crate::ConcreteVersion {
466 &self.$latest_version
467 }
468
469 fn as_any(&self) -> &dyn ::std::any::Any {
470 self
471 }
472 }
473 };
474}
475
476#[doc(hidden)]
480#[macro_export]
481macro_rules! __impl_parse_result_workspace_root {
482 () => {
483 fn workspace_root(&self) -> Option<&::std::path::Path> {
484 None
485 }
486 };
487 ($field:ident) => {
488 fn workspace_root(&self) -> Option<&::std::path::Path> {
489 self.$field.as_deref()
490 }
491 };
492}
493
494#[doc(hidden)]
497#[macro_export]
498macro_rules! __impl_parse_result_dependency_truncation {
499 () => {};
500 ($field:ident) => {
501 fn dependency_truncation(&self) -> Option<(usize, usize)> {
502 self.$field
503 }
504 };
505}
506
507#[doc(hidden)]
510#[macro_export]
511macro_rules! __impl_parse_result_blocked_registries {
512 () => {};
513 ($field:ident) => {
514 fn blocked_registries(&self) -> Vec<$crate::ecosystem::BlockedRegistryOccurrence> {
515 self.$field.clone()
516 }
517 };
518}
519
520#[doc(hidden)]
523#[macro_export]
524macro_rules! __impl_parse_result_rejected_registries {
525 () => {};
526 ($field:ident) => {
527 fn rejected_registries(&self) -> Vec<$crate::ecosystem::RejectedRegistryOccurrence> {
528 self.$field.clone()
529 }
530 };
531}
532
533#[macro_export]
593macro_rules! impl_parse_result {
594 ($type:ty, $dep_type:ty {
595 dependencies: $dependencies:ident,
596 uri: $uri:ident
597 $(, workspace_root: $workspace_root:ident)?
598 $(, dependency_truncation: $dependency_truncation:ident)?
599 $(, blocked_registries: $blocked_registries:ident)?
600 $(, rejected_registries: $rejected_registries:ident)?
601 $(,)?
602 }) => {
603 impl $crate::ecosystem::ParseResult for $type {
604 fn dependencies(&self) -> Vec<&dyn $crate::ecosystem::Dependency> {
605 self.$dependencies
606 .iter()
607 .map(|d| d as &dyn $crate::ecosystem::Dependency)
608 .collect()
609 }
610
611 $crate::__impl_parse_result_workspace_root!($($workspace_root)?);
612
613 fn uri(&self) -> &::url::Url {
614 &self.$uri
615 }
616
617 $crate::__impl_parse_result_dependency_truncation!($($dependency_truncation)?);
618
619 $crate::__impl_parse_result_blocked_registries!($($blocked_registries)?);
620
621 $crate::__impl_parse_result_rejected_registries!($($rejected_registries)?);
622
623 fn as_any(&self) -> &dyn ::std::any::Any {
624 self
625 }
626 }
627 };
628}
629
630#[macro_export]
656macro_rules! impl_registry_versions_method {
657 (get_versions) => {
658 fn get_versions<'a>(
659 &'a self,
660 name: &'a $crate::PackageName,
661 ) -> $crate::ecosystem::BoxFuture<
662 'a,
663 $crate::error::Result<::std::vec::Vec<::std::boxed::Box<dyn $crate::Version>>>,
664 > {
665 ::std::boxed::Box::pin(async move {
666 let versions = self.get_versions(name.as_str()).await?;
667 Ok(versions
668 .into_iter()
669 .map(|v| ::std::boxed::Box::new(v) as ::std::boxed::Box<dyn $crate::Version>)
670 .collect())
671 })
672 }
673 };
674 (get_versions_with) => {
675 fn get_versions_with<'a>(
676 &'a self,
677 name: &'a $crate::PackageName,
678 freshness: $crate::FreshnessSettings,
679 ) -> $crate::ecosystem::BoxFuture<
680 'a,
681 $crate::error::Result<::std::vec::Vec<::std::boxed::Box<dyn $crate::Version>>>,
682 > {
683 ::std::boxed::Box::pin(async move {
684 let versions = self.get_versions_with(name.as_str(), freshness).await?;
685 Ok(versions
686 .into_iter()
687 .map(|v| ::std::boxed::Box::new(v) as ::std::boxed::Box<dyn $crate::Version>)
688 .collect())
689 })
690 }
691 };
692}
693
694#[macro_export]
721macro_rules! impl_get_versions_with_passthrough {
722 ($type:ty, $version:ty $(,)?) => {
723 impl $type {
724 pub async fn get_versions_with(
733 &self,
734 name: &str,
735 _freshness: $crate::FreshnessSettings,
736 ) -> $crate::error::Result<::std::vec::Vec<$version>> {
737 self.get_versions(name).await
738 }
739 }
740 };
741}
742
743#[cfg(test)]
744mod tests {
745 use crate::ConcreteVersion;
746 use crate::position::{Position, Range};
747
748 #[derive(Debug, Clone)]
749 struct TestDependency {
750 name: crate::PackageName,
751 name_range: Range,
752 version_req: Option<crate::VersionReq>,
753 version_range: Option<Range>,
754 }
755
756 #[derive(Debug, Clone)]
757 struct TestDependencyWithSource {
758 name: crate::PackageName,
759 name_range: Range,
760 version_req: Option<crate::VersionReq>,
761 version_range: Option<Range>,
762 source: crate::parser::DependencySource,
763 version_literal: Option<String>,
764 }
765
766 #[derive(Debug, Clone)]
767 struct TestVersion {
768 version: ConcreteVersion,
769 yanked: bool,
770 }
771
772 #[derive(Debug, Clone)]
773 struct TestVersionWithPublishedAt {
774 version: ConcreteVersion,
775 yanked: bool,
776 published_at: Option<crate::freshness::PublishTime>,
777 }
778
779 #[derive(Debug, Clone)]
780 struct TestVersionWithPrerelease {
781 version: ConcreteVersion,
782 yanked: bool,
783 }
784
785 #[derive(Debug, Clone)]
786 struct TestVersionWithPublishedAtAndPrerelease {
787 version: ConcreteVersion,
788 yanked: bool,
789 published_at: Option<crate::freshness::PublishTime>,
790 }
791
792 #[derive(Debug, Clone)]
793 struct TestPackage {
794 name: crate::PackageName,
795 description: Option<String>,
796 repository: Option<String>,
797 homepage: Option<String>,
798 latest_version: ConcreteVersion,
799 }
800
801 #[derive(Debug)]
802 struct TestParseResult {
803 dependencies: Vec<TestDependency>,
804 uri: url::Url,
805 }
806
807 #[derive(Debug)]
808 struct TestParseResultAllOptionals {
809 dependencies: Vec<TestDependency>,
810 uri: url::Url,
811 workspace_root: Option<std::path::PathBuf>,
812 dependency_truncation: Option<(usize, usize)>,
813 blocked_registries: Vec<crate::ecosystem::BlockedRegistryOccurrence>,
814 }
815
816 #[derive(Debug)]
817 struct TestParseResultTruncationAndBlockedRegistries {
818 dependencies: Vec<TestDependency>,
819 uri: url::Url,
820 dependency_truncation: Option<(usize, usize)>,
821 blocked_registries: Vec<crate::ecosystem::BlockedRegistryOccurrence>,
822 }
823
824 impl_dependency!(TestDependency {
825 name: name,
826 name_range: name_range,
827 version: version_req,
828 version_range: version_range,
829 });
830
831 impl_dependency!(TestDependencyWithSource {
832 name: name,
833 name_range: name_range,
834 version: version_req,
835 version_range: version_range,
836 source: source,
837 version_literal: version_literal,
838 });
839
840 impl_version!(TestVersion {
841 version: version,
842 status: |v: &TestVersion| crate::registry::RemovalStatus::from_yanked(v.yanked),
843 });
844
845 impl_version!(TestVersionWithPublishedAt {
846 version: version,
847 status: |v: &TestVersionWithPublishedAt| crate::registry::RemovalStatus::from_yanked(
848 v.yanked
849 ),
850 published_at: published_at,
851 });
852
853 impl_version!(TestVersionWithPrerelease {
854 version: version,
855 status: |v: &TestVersionWithPrerelease| crate::registry::RemovalStatus::from_yanked(
856 v.yanked
857 ),
858 prerelease: |v: &TestVersionWithPrerelease| v.version.as_str().contains(".pre"),
859 });
860
861 impl_version!(TestVersionWithPublishedAtAndPrerelease {
862 version: version,
863 status: |v: &TestVersionWithPublishedAtAndPrerelease| {
864 crate::registry::RemovalStatus::from_yanked(v.yanked)
865 },
866 published_at: published_at,
867 prerelease: |v: &TestVersionWithPublishedAtAndPrerelease| v
868 .version
869 .as_str()
870 .contains(".pre"),
871 });
872
873 impl_metadata!(TestPackage {
874 name: name,
875 description: description,
876 repository: repository,
877 documentation: homepage,
878 latest_version: latest_version,
879 });
880
881 impl_parse_result!(
882 TestParseResult,
883 TestDependency {
884 dependencies: dependencies,
885 uri: uri,
886 }
887 );
888
889 impl_parse_result!(
890 TestParseResultAllOptionals,
891 TestDependency {
892 dependencies: dependencies,
893 uri: uri,
894 workspace_root: workspace_root,
895 dependency_truncation: dependency_truncation,
896 blocked_registries: blocked_registries,
897 }
898 );
899
900 impl_parse_result!(
901 TestParseResultTruncationAndBlockedRegistries,
902 TestDependency {
903 dependencies: dependencies,
904 uri: uri,
905 dependency_truncation: dependency_truncation,
906 blocked_registries: blocked_registries,
907 }
908 );
909
910 #[test]
911 fn test_impl_dependency_macro() {
912 use crate::ecosystem::Dependency;
913
914 let dep = TestDependency {
915 name: "test-pkg".into(),
916 name_range: Range::new(Position::new(0, 0), Position::new(0, 8)),
917 version_req: Some("1.0.0".into()),
918 version_range: Some(Range::new(Position::new(0, 10), Position::new(0, 15))),
919 };
920
921 assert_eq!(dep.name(), "test-pkg");
922 assert_eq!(
923 dep.version_requirement().map(crate::VersionReq::as_str),
924 Some("1.0.0")
925 );
926 assert!(dep.as_any().is::<TestDependency>());
927 assert!(matches!(
928 dep.source(),
929 crate::parser::DependencySource::Registry
930 ));
931 }
932
933 #[test]
934 fn test_impl_dependency_macro_with_source_and_version_literal() {
935 use crate::ecosystem::Dependency;
936
937 let dep = TestDependencyWithSource {
938 name: "test-pkg".into(),
939 name_range: Range::new(Position::new(0, 0), Position::new(0, 8)),
940 version_req: Some("1.0.0".into()),
941 version_range: Some(Range::new(Position::new(0, 10), Position::new(0, 15))),
942 source: crate::parser::DependencySource::Git {
943 url: "https://example.com/repo.git".into(),
944 rev: None,
945 },
946 version_literal: Some("v1.0.0".into()),
947 };
948
949 assert!(matches!(
950 dep.source(),
951 crate::parser::DependencySource::Git { .. }
952 ));
953 assert_eq!(dep.version_literal(), Some("v1.0.0"));
954 }
955
956 #[test]
957 fn test_impl_version_macro() {
958 use crate::registry::Version;
959
960 let version = TestVersion {
961 version: "2.0.0".into(),
962 yanked: true,
963 };
964
965 assert_eq!(version.version_string().as_str(), "2.0.0");
966 assert!(version.removal_status().blocks_resolution());
967 assert!(version.as_any().is::<TestVersion>());
968 assert!(version.published_at().is_none());
969 }
970
971 #[test]
972 fn test_impl_version_macro_with_published_at() {
973 use crate::freshness::PublishTime;
974 use crate::registry::Version;
975
976 let version = TestVersionWithPublishedAt {
977 version: "3.0.0".into(),
978 yanked: false,
979 published_at: Some(PublishTime::from_unix_secs(1_000)),
980 };
981
982 assert_eq!(version.version_string().as_str(), "3.0.0");
983 assert!(!version.removal_status().blocks_resolution());
984 assert_eq!(
985 version.published_at(),
986 Some(PublishTime::from_unix_secs(1_000))
987 );
988 assert!(version.as_any().is::<TestVersionWithPublishedAt>());
989 }
990
991 #[test]
992 fn test_impl_version_macro_with_prerelease() {
993 use crate::registry::Version;
994
995 let stable = TestVersionWithPrerelease {
996 version: "1.0.0".into(),
997 yanked: false,
998 };
999 let prerelease = TestVersionWithPrerelease {
1000 version: "1.0.0.pre1".into(),
1001 yanked: false,
1002 };
1003
1004 assert!(!stable.is_prerelease());
1005 assert!(prerelease.is_prerelease());
1006 assert!(stable.is_stable());
1007 assert!(!prerelease.is_stable());
1008 }
1009
1010 #[test]
1011 fn test_impl_version_macro_with_published_at_and_prerelease() {
1012 use crate::freshness::PublishTime;
1013 use crate::registry::Version;
1014
1015 let version = TestVersionWithPublishedAtAndPrerelease {
1016 version: "2.0.0.pre1".into(),
1017 yanked: false,
1018 published_at: Some(PublishTime::from_unix_secs(2_000)),
1019 };
1020
1021 assert!(version.is_prerelease());
1022 assert_eq!(
1023 version.published_at(),
1024 Some(PublishTime::from_unix_secs(2_000))
1025 );
1026 }
1027
1028 #[test]
1029 fn test_impl_metadata_macro() {
1030 use crate::registry::Metadata;
1031
1032 let pkg = TestPackage {
1033 name: crate::PackageName::new("my-pkg"),
1034 description: Some("A test package".into()),
1035 repository: Some("user/repo".into()),
1036 homepage: Some("https://example.com".into()),
1037 latest_version: "3.0.0".into(),
1038 };
1039
1040 assert_eq!(pkg.name(), "my-pkg");
1041 assert_eq!(pkg.description(), Some("A test package"));
1042 assert_eq!(pkg.documentation(), Some("https://example.com"));
1043 assert!(pkg.as_any().is::<TestPackage>());
1044 }
1045
1046 #[test]
1047 fn test_impl_parse_result_macro() {
1048 use crate::ecosystem::ParseResult;
1049
1050 let result = TestParseResult {
1051 dependencies: vec![TestDependency {
1052 name: "dep1".into(),
1053 name_range: Range::default(),
1054 version_req: None,
1055 version_range: None,
1056 }],
1057 uri: crate::test_util::test_uri("/test"),
1058 };
1059
1060 assert_eq!(result.dependencies().len(), 1);
1061 assert!(result.workspace_root().is_none());
1062 assert!(result.as_any().is::<TestParseResult>());
1063 }
1064
1065 #[test]
1066 fn test_impl_parse_result_macro_all_optionals() {
1067 use crate::ecosystem::{BlockedRegistryOccurrence, ParseResult};
1068 use crate::net_policy::HostClass;
1069
1070 let result = TestParseResultAllOptionals {
1071 dependencies: vec![TestDependency {
1072 name: "dep1".into(),
1073 name_range: Range::default(),
1074 version_req: None,
1075 version_range: None,
1076 }],
1077 uri: crate::test_util::test_uri("/test"),
1078 workspace_root: Some(std::path::PathBuf::from("/workspace")),
1079 dependency_truncation: Some((5, 10)),
1080 blocked_registries: vec![BlockedRegistryOccurrence {
1081 range: Range::default(),
1082 class: HostClass::Loopback,
1083 raw_value: "registry".into(),
1084 declaration_key: "key".into(),
1085 }],
1086 };
1087
1088 assert_eq!(result.dependencies().len(), 1);
1089 assert_eq!(
1090 result.workspace_root(),
1091 Some(std::path::Path::new("/workspace"))
1092 );
1093 assert_eq!(result.dependency_truncation(), Some((5, 10)));
1094 assert_eq!(result.blocked_registries().len(), 1);
1095 assert!(result.as_any().is::<TestParseResultAllOptionals>());
1096 }
1097
1098 #[test]
1099 fn test_impl_parse_result_macro_truncation_and_blocked_registries() {
1100 use crate::ecosystem::{BlockedRegistryOccurrence, ParseResult};
1101 use crate::net_policy::HostClass;
1102
1103 let result = TestParseResultTruncationAndBlockedRegistries {
1104 dependencies: vec![],
1105 uri: crate::test_util::test_uri("/test"),
1106 dependency_truncation: Some((3, 7)),
1107 blocked_registries: vec![BlockedRegistryOccurrence {
1108 range: Range::default(),
1109 class: HostClass::Loopback,
1110 raw_value: "registry".into(),
1111 declaration_key: "key".into(),
1112 }],
1113 };
1114
1115 assert!(result.workspace_root().is_none());
1116 assert_eq!(result.dependency_truncation(), Some((3, 7)));
1117 assert_eq!(result.blocked_registries().len(), 1);
1118 assert!(
1119 result
1120 .as_any()
1121 .is::<TestParseResultTruncationAndBlockedRegistries>()
1122 );
1123 }
1124}