cargo_lock/lockfile/
version.rs1use super::encoding::EncodablePackage;
4use crate::{
5 error::{Error, Result},
6 metadata::Metadata,
7};
8use serde::{Deserialize, Serialize};
9use std::str::FromStr;
10
11#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)]
13#[non_exhaustive]
14#[repr(u32)]
15pub enum ResolveVersion {
16 V1 = 1,
19
20 V2 = 2,
26
27 V3 = 3,
33
34 V4 = 4,
39}
40
41impl ResolveVersion {
42 pub(super) fn detect(packages: &[EncodablePackage], metadata: &Metadata) -> Result<Self> {
44 let is_v1 = metadata.keys().any(|key| key.is_checksum());
46
47 let is_v2 = packages.iter().any(|package| package.checksum.is_some());
49
50 if is_v1 && is_v2 {
51 return Err(Error::Parse("malformed lockfile: contains checksums in both [[package]] and [[metadata]] sections".to_string()));
52 }
53
54 if is_v1 {
55 Ok(ResolveVersion::V1)
56 } else {
57 Ok(ResolveVersion::V2)
59 }
60 }
61
62 pub(super) fn is_explicit(self) -> bool {
64 u32::from(self) >= 3
65 }
66}
67
68impl Default for ResolveVersion {
70 fn default() -> Self {
71 ResolveVersion::V3
72 }
73}
74
75impl From<ResolveVersion> for u32 {
76 fn from(version: ResolveVersion) -> u32 {
77 version as u32
78 }
79}
80
81impl FromStr for ResolveVersion {
82 type Err = Error;
83
84 fn from_str(s: &str) -> Result<Self> {
85 u32::from_str(s)
86 .map_err(|_| Error::Parse(format!("invalid Cargo.lock format version: `{s}`")))
87 .and_then(Self::try_from)
88 }
89}
90
91impl TryFrom<u32> for ResolveVersion {
92 type Error = Error;
93
94 fn try_from(num: u32) -> Result<Self> {
95 match num {
96 1 => Ok(ResolveVersion::V1),
97 2 => Ok(ResolveVersion::V2),
98 3 => Ok(ResolveVersion::V3),
99 4 => Ok(ResolveVersion::V4),
100 _ => Err(Error::Parse(format!(
101 "invalid Cargo.lock format version: `{num}`"
102 ))),
103 }
104 }
105}