1#![warn(
2 clippy::all,
3 clippy::pedantic,
4 clippy::restriction,
5 clippy::nursery,
6 clippy::cargo
7)]
8#![allow(
9 clippy::integer_arithmetic,
11 clippy::float_arithmetic,
12 clippy::blanket_clippy_restriction_lints,
13 clippy::implicit_return,
14 clippy::enum_glob_use,
15 clippy::wildcard_enum_match_arm,
16 clippy::pattern_type_mismatch,
17 clippy::shadow_reuse,
18 clippy::shadow_same,
19 clippy::shadow_unrelated,
20 clippy::must_use_candidate,
21 clippy::clone_on_ref_ptr,
22 clippy::multiple_crate_versions,
23 clippy::default_numeric_fallback,
24 clippy::map_err_ignore,
25
26 clippy::expect_used,
28
29 clippy::missing_inline_in_public_items,
31 clippy::exhaustive_structs,
32 clippy::exhaustive_enums,
33 clippy::module_name_repetitions,
34 clippy::unseparated_literal_suffix,
35 clippy::self_named_module_files,
36 clippy::wildcard_dependencies,
42 clippy::redundant_feature_names,
43 clippy::cargo_common_metadata,
44
45 clippy::missing_docs_in_private_items,
47 clippy::missing_errors_doc,
48
49 clippy::todo,
51 clippy::panic_in_result_fn,
52 clippy::panic,
53 clippy::unimplemented,
54 clippy::unreachable,
55
56 clippy::negative_feature_names
57)]
58
59pub mod constants;
60use anyhow::{anyhow, bail};
61
62#[derive(Debug, Default)]
63pub struct PackageName(String);
64
65impl ToString for PackageName {
66 fn to_string(&self) -> String {
67 format!(
68 "{namespace}/{name}",
69 namespace = self.namespace(),
70 name = self.package()
71 )
72 }
73}
74
75#[allow(clippy::indexing_slicing)]
76impl PackageName {
77 pub fn namespace(&self) -> &str {
79 let parts = self.0.split('/').collect::<Vec<_>>();
80 parts[0]
81 }
82
83 pub fn package(&self) -> &str {
85 let parts = self.0.split('/').collect::<Vec<_>>();
86 parts[1]
87 }
88}
89
90#[allow(clippy::indexing_slicing)]
91impl TryFrom<String> for PackageName {
92 type Error = anyhow::Error;
93 fn try_from(package_name: String) -> Result<Self, Self::Error> {
94 let parts = package_name.split('/').collect::<Vec<_>>();
96 if parts.len() != 2 {
97 bail!("Invalid package name `{package_name}` - Package name must consist of namespace and per-namespace-name", package_name = package_name );
98 }
99 if parts[0]
100 .chars()
101 .next()
102 .ok_or_else(|| anyhow!("Package name prefix doesn't consist of any characters"))?
103 != '@'
104 {
105 bail!("Invalid namespace `{namespace}` of `{package_name}` - Namespace must have `@` as a first character", package_name = package_name, namespace= parts[0] );
106 }
107 Ok(Self(package_name))
108 }
109}