diff --git a/Cargo.lock b/Cargo.lock index 014618e83..7de6fe126 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -876,7 +876,7 @@ name = "distribution-filename" version = "0.0.1" dependencies = [ "insta", - "pep440_rs 0.4.0", + "pep440_rs", "platform-tags", "rkyv", "serde", @@ -896,7 +896,7 @@ dependencies = [ "fs-err", "itertools 0.12.1", "once_cell", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "platform-tags", "pypi-types", @@ -1588,7 +1588,7 @@ dependencies = [ "indoc", "mailparse", "once_cell", - "pep440_rs 0.4.0", + "pep440_rs", "platform-host", "platform-info", "plist", @@ -2156,16 +2156,6 @@ dependencies = [ "parking_lot_core 0.8.6", ] -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.9", -] - [[package]] name = "parking_lot_core" version = "0.8.6" @@ -2201,19 +2191,7 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pep440_rs" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887f66cc62717ea72caac4f1eb4e6f392224da3ffff3f40ec13ab427802746d6" -dependencies = [ - "lazy_static", - "regex", - "serde", - "unicode-width", -] - -[[package]] -name = "pep440_rs" -version = "0.4.0" +version = "0.5.0" dependencies = [ "indoc", "once_cell", @@ -2228,13 +2206,13 @@ dependencies = [ [[package]] name = "pep508_rs" -version = "0.2.3" +version = "0.4.2" dependencies = [ "derivative", "indoc", "log", "once_cell", - "pep440_rs 0.4.0", + "pep440_rs", "pyo3", "pyo3-log", "regex", @@ -2496,7 +2474,7 @@ dependencies = [ "indoc", "libc", "memoffset", - "parking_lot 0.12.1", + "parking_lot", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", @@ -2567,7 +2545,7 @@ dependencies = [ "insta", "mailparse", "once_cell", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "regex", "rkyv", @@ -2583,12 +2561,12 @@ dependencies = [ [[package]] name = "pyproject-toml" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46d4a5e69187f23a29f8aa0ea57491d104ba541bc55f76552c2a74962aa20e04" +checksum = "3b80f889b6d413c3f8963a2c7db03f95dd6e1d85e1074137cb2013ea2faa8898" dependencies = [ "indexmap 2.2.3", - "pep440_rs 0.3.12", + "pep440_rs", "pep508_rs", "serde", "toml", @@ -2793,7 +2771,7 @@ dependencies = [ "insta", "itertools 0.10.5", "once_cell", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "regex", "serde", @@ -2882,7 +2860,7 @@ dependencies = [ "getrandom", "http", "hyper", - "parking_lot 0.11.2", + "parking_lot", "reqwest", "reqwest-middleware", "retry-policies", @@ -4185,7 +4163,7 @@ dependencies = [ "miette", "mimalloc", "owo-colors 4.0.0", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "platform-host", "platform-tags", @@ -4292,7 +4270,7 @@ dependencies = [ "http", "insta", "install-wheel-rs", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "platform-tags", "pypi-types", @@ -4338,7 +4316,7 @@ dependencies = [ "itertools 0.12.1", "mimalloc", "owo-colors 4.0.0", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "petgraph", "platform-host", @@ -4410,7 +4388,7 @@ dependencies = [ "futures", "install-wheel-rs", "nanoid", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "platform-tags", "pypi-types", @@ -4502,7 +4480,7 @@ dependencies = [ "futures", "install-wheel-rs", "once-map", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "platform-tags", "pypi-types", @@ -4536,7 +4514,7 @@ dependencies = [ "insta", "itertools 0.12.1", "once_cell", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "platform-host", "platform-tags", @@ -4586,7 +4564,7 @@ dependencies = [ "once-map", "once_cell", "owo-colors 4.0.0", - "pep440_rs 0.4.0", + "pep440_rs", "pep508_rs", "petgraph", "platform-host", @@ -4812,7 +4790,7 @@ checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ "futures", "js-sys", - "parking_lot 0.11.2", + "parking_lot", "pin-utils", "wasm-bindgen", "wasm-bindgen-futures", diff --git a/Cargo.toml b/Cargo.toml index 56fe1764f..95b7be036 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,7 @@ plist = { version = "1.6.0" } pubgrub = { git = "https://github.com/zanieb/pubgrub", rev = "9b6d89cb8a0c7902815c8b2ae99106ba322ffb14" } pyo3 = { version = "0.20.2" } pyo3-log = { version = "0.9.0"} -pyproject-toml = { version = "0.8.1" } +pyproject-toml = { version = "0.10.0" } rand = { version = "0.8.5" } rayon = { version = "1.8.0" } reflink-copy = { version = "0.1.14" } diff --git a/crates/pep440-rs/Cargo.toml b/crates/pep440-rs/Cargo.toml index bf4645ba7..d7273b94b 100644 --- a/crates/pep440-rs/Cargo.toml +++ b/crates/pep440-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pep440_rs" -version = "0.4.0" +version = "0.5.0" description = "A library for python version numbers and specifiers, implementing PEP 440" license = "Apache-2.0 OR BSD-2-Clause" include = ["/src", "Changelog.md", "License-Apache", "License-BSD", "Readme.md", "pyproject.toml"] diff --git a/crates/pep440-rs/Readme.md b/crates/pep440-rs/Readme.md index 295f0b4c5..7fa8fb3f5 100644 --- a/crates/pep440-rs/Readme.md +++ b/crates/pep440-rs/Readme.md @@ -16,7 +16,7 @@ let version = Version::from_str("1.19").unwrap(); let version_specifier = VersionSpecifier::from_str("==1.*").unwrap(); assert!(version_specifier.contains(&version)); let version_specifiers = parse_version_specifiers(">=1.16, <2.0").unwrap(); -assert!(version_specifiers.iter().all(|specifier| specifier.contains(&version))); +assert!(version_specifiers.contains(&version)); ``` In python (`pip install pep440_rs`): diff --git a/crates/pep440-rs/src/lib.rs b/crates/pep440-rs/src/lib.rs index 2e72e202e..b96bf0044 100644 --- a/crates/pep440-rs/src/lib.rs +++ b/crates/pep440-rs/src/lib.rs @@ -9,7 +9,7 @@ //! let version_specifier = VersionSpecifier::from_str("== 1.*").unwrap(); //! assert!(version_specifier.contains(&version)); //! let version_specifiers = VersionSpecifiers::from_str(">=1.16, <2.0").unwrap(); -//! assert!(version_specifiers.iter().all(|specifier| specifier.contains(&version))); +//! assert!(version_specifiers.contains(&version)); //! ``` //! //! PEP 440 has a lot of unintuitive features, including: @@ -41,9 +41,7 @@ pub use { LocalSegment, Operator, OperatorParseError, PreRelease, PreReleaseKind, Version, VersionParseError, VersionPattern, VersionPatternParseError, MIN_VERSION, }, - version_specifier::{ - parse_version_specifiers, VersionSpecifier, VersionSpecifiers, VersionSpecifiersParseError, - }, + version_specifier::{VersionSpecifier, VersionSpecifiers, VersionSpecifiersParseError}, }; mod version; diff --git a/crates/pep440-rs/src/version.rs b/crates/pep440-rs/src/version.rs index 480eeaed7..118b2a647 100644 --- a/crates/pep440-rs/src/version.rs +++ b/crates/pep440-rs/src/version.rs @@ -2291,7 +2291,7 @@ fn parse_u64(bytes: &[u8]) -> Result { Ok(n) } -/// The minimum version that can be represented by a [`Version`]. +/// The minimum version that can be represented by a [`Version`]: `0a0.dev0`. pub static MIN_VERSION: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| Version::from_str("0a0.dev0").unwrap()); diff --git a/crates/pep440-rs/src/version_specifier.rs b/crates/pep440-rs/src/version_specifier.rs index f3e1693a2..946f361be 100644 --- a/crates/pep440-rs/src/version_specifier.rs +++ b/crates/pep440-rs/src/version_specifier.rs @@ -697,19 +697,8 @@ impl From for VersionSpecifierParseError { } } -/// Parses a list of specifiers such as `>= 1.0, != 1.3.*, < 2.0`. -/// -/// I recommend using [`VersionSpecifiers::from_str`] instead. -/// -/// ```rust -/// use std::str::FromStr; -/// use pep440_rs::{parse_version_specifiers, Version}; -/// -/// let version = Version::from_str("1.19").unwrap(); -/// let version_specifiers = parse_version_specifiers(">=1.16, <2.0").unwrap(); -/// assert!(version_specifiers.iter().all(|specifier| specifier.contains(&version))); -/// ``` -pub fn parse_version_specifiers( +/// Parse a list of specifiers such as `>= 1.0, != 1.3.*, < 2.0`. +pub(crate) fn parse_version_specifiers( spec: &str, ) -> Result, VersionSpecifiersParseError> { let mut version_ranges = Vec::new(); diff --git a/crates/pep508-rs/Cargo.toml b/crates/pep508-rs/Cargo.toml index e0ca16771..3aba398e0 100644 --- a/crates/pep508-rs/Cargo.toml +++ b/crates/pep508-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pep508_rs" -version = "0.2.3" +version = "0.4.2" description = "A library for python dependency specifiers, better known as PEP 508" include = ["/src", "Changelog.md", "License-Apache", "License-BSD", "Readme.md", "pyproject.toml"] license = "Apache-2.0 OR BSD-2-Clause" @@ -30,9 +30,9 @@ rkyv = { workspace = true, features = ["strict"], optional = true } serde = { workspace = true, features = ["derive"], optional = true } serde_json = { workspace = true, optional = true } thiserror = { workspace = true } -tracing = { workspace = true, features = ["log"] } +tracing = { workspace = true, optional = true } unicode-width = { workspace = true } -url = { workspace = true, features = ["serde"] } +url = { workspace = true } [dev-dependencies] indoc = { version = "2.0.4" } @@ -41,7 +41,15 @@ serde_json = { version = "1.0.111" } testing_logger = { version = "0.1.1" } [features] -pyo3 = ["dep:pyo3", "pep440_rs/pyo3", "pyo3-log"] -rkyv = ["dep:rkyv", "pep440_rs/rkyv"] -serde = ["dep:serde", "pep440_rs/serde"] +pyo3 = ["dep:pyo3", "pep440_rs/pyo3", "pyo3-log", "tracing", "tracing/log"] +rkyv = ["dep:rkyv", "pep440_rs/rkyv", "uv-normalize/rkyv"] +serde = ["dep:serde", "pep440_rs/serde", "uv-normalize/serde", "url/serde"] +tracing = ["dep:tracing", "pep440_rs/tracing"] +# PEP 508 allows only URLs such as `foo @ https://example.org/foo` or `foo @ file:///home/ferris/foo`, and +# arguably does not allow relative paths in file URLs (`foo @ file://./foo`, +# `foo @ file:foo-3.0.0-py3-none-any.whl`, `foo @ file://foo-3.0.0-py3-none-any.whl`), as they are not part of the +# relevant RFCs, even though widely supported. Pip accepts relative file URLs and paths instead of urls +# (`foo @ ./foo-3.0.0-py3-none-any.whl`). The `non-pep508-features` controls whether these non-spec features will +# be supported. +non-pep508-extensions = [] default = [] diff --git a/crates/pep508-rs/src/lib.rs b/crates/pep508-rs/src/lib.rs index ede41701c..fa1a797c7 100644 --- a/crates/pep508-rs/src/lib.rs +++ b/crates/pep508-rs/src/lib.rs @@ -14,7 +14,7 @@ //! assert_eq!(dependency_specification.extras, vec![ExtraName::from_str("security").unwrap(), ExtraName::from_str("tests").unwrap()]); //! ``` -#![deny(missing_docs)] +#![warn(missing_docs)] #[cfg(feature = "pyo3")] use std::collections::hash_map::DefaultHasher; @@ -738,7 +738,7 @@ fn parse_url(cursor: &mut Cursor, working_dir: Option<&Path>) -> Result, + #[cfg_attr(not(feature = "non-pep508-extensions"), allow(unused))] working_dir: Option<&Path>, cursor: &Cursor, start: usize, len: usize, @@ -752,20 +752,22 @@ fn preprocess_url( // Transform, e.g., `/C:/Users/ferris/wheel-0.42.0.tar.gz` to `C:\Users\ferris\wheel-0.42.0.tar.gz`. let path = normalize_url_path(path); + #[cfg(feature = "non-pep508-extensions")] if let Some(working_dir) = working_dir { - VerbatimUrl::from_path(path, working_dir).with_given(url.to_string()) - } else { - VerbatimUrl::from_absolute_path(path) - .map_err(|err| Pep508Error { - message: Pep508ErrorSource::UrlError(err), - start, - len, - input: cursor.to_string(), - })? - .with_given(url.to_string()) + return Ok( + VerbatimUrl::from_path(path, working_dir).with_given(url.to_string()) + ); } - } + VerbatimUrl::from_absolute_path(path) + .map_err(|err| Pep508Error { + message: Pep508ErrorSource::UrlError(err), + start, + len, + input: cursor.to_string(), + })? + .with_given(url.to_string()) + } // Ex) `https://download.pytorch.org/whl/torch_stable.html` Some(_) => { // Ex) `https://download.pytorch.org/whl/torch_stable.html` @@ -795,18 +797,19 @@ fn preprocess_url( } } else { // Ex) `../editable/` + #[cfg(feature = "non-pep508-extensions")] if let Some(working_dir) = working_dir { - VerbatimUrl::from_path(url, working_dir).with_given(url.to_string()) - } else { - VerbatimUrl::from_absolute_path(url) - .map_err(|err| Pep508Error { - message: Pep508ErrorSource::UrlError(err), - start, - len, - input: cursor.to_string(), - })? - .with_given(url.to_string()) + return Ok(VerbatimUrl::from_path(url, working_dir).with_given(url.to_string())); } + + VerbatimUrl::from_absolute_path(url) + .map_err(|err| Pep508Error { + message: Pep508ErrorSource::UrlError(err), + start, + len, + input: cursor.to_string(), + })? + .with_given(url.to_string()) }; Ok(url) } @@ -1045,6 +1048,7 @@ pub fn python_module(py: Python<'_>, m: &PyModule) -> PyResult<()> { /// Half of these tests are copied from #[cfg(test)] mod tests { + use std::env; use std::str::FromStr; use indoc::indoc; @@ -1629,4 +1633,26 @@ mod tests { }, ); } + + /// Check that the relative path support feature toggle works. + #[test] + fn non_pep508_paths() { + let requirements = &[ + "foo @ file://./foo", + "foo @ file://foo-3.0.0-py3-none-any.whl", + "foo @ file:foo-3.0.0-py3-none-any.whl", + "foo @ ./foo-3.0.0-py3-none-any.whl", + ]; + let cwd = env::current_dir().unwrap(); + + for requirement in requirements { + assert_eq!( + Requirement::parse(requirement, &cwd).is_ok(), + cfg!(feature = "non-pep508-extensions"), + "{}: {:?}", + requirement, + Requirement::parse(requirement, &cwd) + ); + } + } } diff --git a/crates/pep508-rs/src/marker.rs b/crates/pep508-rs/src/marker.rs index 4445f8cbd..7b09d0aa1 100644 --- a/crates/pep508-rs/src/marker.rs +++ b/crates/pep508-rs/src/marker.rs @@ -21,7 +21,6 @@ use std::collections::HashSet; use std::fmt::{Display, Formatter}; use std::ops::Deref; use std::str::FromStr; -use tracing::warn; use uv_normalize::ExtraName; /// Ways in which marker evaluation can fail @@ -944,8 +943,11 @@ impl FromStr for MarkerTree { impl MarkerTree { /// Does this marker apply in the given environment? pub fn evaluate(&self, env: &MarkerEnvironment, extras: &[ExtraName]) -> bool { - let mut reporter = |_kind, message, _marker_expression: &MarkerExpression| { - warn!("{}", message); + let mut reporter = |_kind, _message, _marker_expression: &MarkerExpression| { + #[cfg(feature = "tracing")] + { + tracing::warn!("{}", _message); + } }; self.report_deprecated_options(&mut reporter); match self { @@ -1347,7 +1349,6 @@ mod test { use crate::marker::{MarkerEnvironment, StringVersion}; use crate::{MarkerExpression, MarkerOperator, MarkerTree, MarkerValue, MarkerValueString}; use indoc::indoc; - use log::Level; use std::str::FromStr; fn assert_err(input: &str, error: &str) { @@ -1443,6 +1444,7 @@ mod test { } #[test] + #[cfg(feature = "tracing")] fn warnings() { let env37 = env37(); testing_logger::setup(); @@ -1453,7 +1455,7 @@ mod test { captured_logs[0].body, "Comparing two markers with each other doesn't make any sense, evaluating to false" ); - assert_eq!(captured_logs[0].level, Level::Warn); + assert_eq!(captured_logs[0].level, log::Level::Warn); assert_eq!(captured_logs.len(), 1); }); let non_pep440 = MarkerTree::from_str("python_version >= '3.9.'").unwrap(); @@ -1465,7 +1467,7 @@ mod test { evaluating to false: after parsing 3.9, found \".\" after it, \ which is not part of a valid version" ); - assert_eq!(captured_logs[0].level, Level::Warn); + assert_eq!(captured_logs[0].level, log::Level::Warn); assert_eq!(captured_logs.len(), 1); }); let string_string = MarkerTree::from_str("'b' >= 'a'").unwrap(); @@ -1475,7 +1477,7 @@ mod test { captured_logs[0].body, "Comparing two quoted strings with each other doesn't make sense: 'b' >= 'a', evaluating to false" ); - assert_eq!(captured_logs[0].level, Level::Warn); + assert_eq!(captured_logs[0].level, log::Level::Warn); assert_eq!(captured_logs.len(), 1); }); let string_string = MarkerTree::from_str(r#"os.name == 'posix' and platform.machine == 'x86_64' and platform.python_implementation == 'CPython' and 'Ubuntu' in platform.version and sys.platform == 'linux'"#).unwrap(); @@ -1484,7 +1486,7 @@ mod test { let messages: Vec<_> = captured_logs .iter() .map(|message| { - assert_eq!(message.level, Level::Warn); + assert_eq!(message.level, log::Level::Warn); &message.body }) .collect(); diff --git a/crates/pep508-rs/src/verbatim_url.rs b/crates/pep508-rs/src/verbatim_url.rs index f4208e053..558022744 100644 --- a/crates/pep508-rs/src/verbatim_url.rs +++ b/crates/pep508-rs/src/verbatim_url.rs @@ -35,7 +35,8 @@ impl VerbatimUrl { Ok(Self { url, given: None }) } - /// Parse a URL from am absolute or relative path. + /// Parse a URL from an absolute or relative path. + #[cfg(feature = "non-pep508-extensions")] // PEP 508 arguably only allows absolute file URLs. pub fn from_path(path: impl AsRef, working_dir: impl AsRef) -> Self { // Expand any environment variables. let path = PathBuf::from(expand_env_vars(path.as_ref(), false).as_ref()); diff --git a/crates/requirements-txt/Cargo.toml b/crates/requirements-txt/Cargo.toml index 0141dda91..f6a6e5713 100644 --- a/crates/requirements-txt/Cargo.toml +++ b/crates/requirements-txt/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] pep440_rs = { path = "../pep440-rs", features = ["rkyv", "serde"] } -pep508_rs = { path = "../pep508-rs", features = ["rkyv", "serde"] } +pep508_rs = { path = "../pep508-rs", features = ["rkyv", "serde", "non-pep508-extensions"] } uv-fs = { path = "../uv-fs" } uv-normalize = { path = "../uv-normalize" } uv-warnings = { path = "../uv-warnings" } diff --git a/crates/uv-normalize/Cargo.toml b/crates/uv-normalize/Cargo.toml index 0e2c79dfa..58889d97d 100644 --- a/crates/uv-normalize/Cargo.toml +++ b/crates/uv-normalize/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" description = "Normalization for distribution, package and extra anmes" [dependencies] -serde = { workspace = true, features = ["derive"] } -rkyv = { workspace = true, features = ["strict", "validation"] } +serde = { workspace = true, features = ["derive"], optional = true } +rkyv = { workspace = true, features = ["strict", "validation"], optional = true } diff --git a/crates/uv-normalize/src/extra_name.rs b/crates/uv-normalize/src/extra_name.rs index d26dda2f2..8c1c94e7b 100644 --- a/crates/uv-normalize/src/extra_name.rs +++ b/crates/uv-normalize/src/extra_name.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize}; use std::fmt; use std::fmt::{Display, Formatter}; @@ -13,7 +14,8 @@ use crate::{validate_and_normalize_owned, validate_and_normalize_ref, InvalidNam /// See: /// - /// - -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)] +#[cfg_attr(feature = "serde", derive(Serialize))] +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ExtraName(String); impl ExtraName { @@ -31,6 +33,7 @@ impl FromStr for ExtraName { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for ExtraName { fn deserialize(deserializer: D) -> Result where diff --git a/crates/uv-normalize/src/lib.rs b/crates/uv-normalize/src/lib.rs index ffff38065..2dfb1cd8a 100644 --- a/crates/uv-normalize/src/lib.rs +++ b/crates/uv-normalize/src/lib.rs @@ -90,6 +90,7 @@ fn is_normalized(name: impl AsRef) -> Result { Ok(true) } +/// Invalid [`crate::PackageName`] or [`crate::ExtraName`]. #[derive(Clone, Debug, Eq, PartialEq)] pub struct InvalidNameError(String); diff --git a/crates/uv-normalize/src/package_name.rs b/crates/uv-normalize/src/package_name.rs index 6bbd69ee7..5ea4ce903 100644 --- a/crates/uv-normalize/src/package_name.rs +++ b/crates/uv-normalize/src/package_name.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::str::FromStr; +#[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize}; use crate::{validate_and_normalize_owned, validate_and_normalize_ref, InvalidNameError}; @@ -11,21 +12,14 @@ use crate::{validate_and_normalize_owned, validate_and_normalize_ref, InvalidNam /// down to a single `-`, e.g., `---`, `.`, and `__` all get converted to just `-`. /// /// See: -#[derive( - Debug, - Clone, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - Serialize, - rkyv::Archive, - rkyv::Deserialize, - rkyv::Serialize, +#[cfg_attr(feature = "serde", derive(Serialize))] +#[cfg_attr( + feature = "rkyv", + derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize), + archive(check_bytes), + archive_attr(derive(Debug)) )] -#[archive(check_bytes)] -#[archive_attr(derive(Debug))] +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct PackageName(String); impl PackageName { @@ -75,6 +69,7 @@ impl FromStr for PackageName { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for PackageName { fn deserialize(deserializer: D) -> Result where