plow_ontology/
lib.rs

1#![warn(
2    clippy::all,
3    clippy::pedantic,
4    clippy::restriction,
5    clippy::nursery,
6    clippy::cargo
7)]
8#![allow(
9    // Group of too restrictive lints
10    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    // We decided that we're ok with expect
27    clippy::expect_used,
28
29    // Too restrictive for the current style
30    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    // Currently breaks CI, let's wait a bit more until new clippy version is more spread.
37    // clippy::single_char_lifetime_names,
38
39    // Allowed lints related to cargo
40    // (comment these out if you'd like to improve Cargo.toml)
41    clippy::wildcard_dependencies,
42    clippy::redundant_feature_names,
43    clippy::cargo_common_metadata,
44
45    // Comment these out when writing docs
46    clippy::missing_docs_in_private_items,
47    clippy::missing_errors_doc,
48
49    // Comment these out before submitting a PR
50    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    /// Returns the namespace of the package name (including `@` prefix).
78    pub fn namespace(&self) -> &str {
79        let parts = self.0.split('/').collect::<Vec<_>>();
80        parts[0]
81    }
82
83    /// Returns the name of the package.
84    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        // TODO: verify allowed characters
95        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}