Skip to content
1 change: 1 addition & 0 deletions crates/cargo-util-schemas/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

pub mod core;
pub mod index;
pub mod lockfile;
pub mod manifest;
pub mod messages;
#[cfg(feature = "unstable-schema")]
Expand Down
36 changes: 36 additions & 0 deletions crates/cargo-util-schemas/src/lockfile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct EncodableSourceIdError(#[from] pub EncodableSourceIdErrorKind);

#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
pub enum EncodableSourceIdErrorKind {
#[error("invalid source `{0}`")]
InvalidSource(String),

#[error("invalid url `{url}`: {msg}")]
InvalidUrl { url: String, msg: String },

#[error("unsupported source protocol: {0}")]
UnsupportedSource(String),
}

#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct EncodablePackageIdError(#[from] EncodablePackageIdErrorKind);

impl From<EncodableSourceIdError> for EncodablePackageIdError {
fn from(value: EncodableSourceIdError) -> Self {
EncodablePackageIdErrorKind::Source(value).into()
}
}

#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
pub enum EncodablePackageIdErrorKind {
#[error("invalid serialied PackageId")]
InvalidSerializedPackageId,

#[error(transparent)]
Source(#[from] EncodableSourceIdError),
}
28 changes: 18 additions & 10 deletions src/cargo/core/resolver/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ use crate::util::interning::InternedString;
use crate::util::{Graph, internal};
use anyhow::{Context as _, bail};
use cargo_util_schemas::core::SourceKind;
use cargo_util_schemas::lockfile::{
EncodablePackageIdError, EncodablePackageIdErrorKind, EncodableSourceIdError,
EncodableSourceIdErrorKind,
};
use serde::de;
use serde::ser;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -550,14 +554,16 @@ pub struct EncodableSourceId {
}

impl EncodableSourceId {
pub fn new(source: String) -> CargoResult<Self> {
pub fn new(source: String) -> Result<Self, EncodableSourceIdError> {
let source_str = source.clone();
let (kind, url) = source
.split_once('+')
.ok_or_else(|| anyhow::format_err!("invalid source `{}`", source_str))?;
let (kind, url) = source.split_once('+').ok_or_else(|| {
EncodableSourceIdError(EncodableSourceIdErrorKind::InvalidSource(source.clone()).into())
})?;

let url =
Url::parse(url).map_err(|s| anyhow::format_err!("invalid url `{}`: {}", url, s))?;
let url = Url::parse(url).map_err(|msg| EncodableSourceIdErrorKind::InvalidUrl {
url: url.to_string(),
msg: msg.to_string(),
})?;

let kind = match kind {
"git" => {
Expand All @@ -567,7 +573,9 @@ impl EncodableSourceId {
"registry" => SourceKind::Registry,
"sparse" => SourceKind::SparseRegistry,
"path" => SourceKind::Path,
kind => anyhow::bail!("unsupported source protocol: {}", kind),
kind => {
return Err(EncodableSourceIdErrorKind::UnsupportedSource(kind.to_string()).into());
}
};

Ok(Self {
Expand Down Expand Up @@ -663,9 +671,9 @@ impl fmt::Display for EncodablePackageId {
}

impl FromStr for EncodablePackageId {
type Err = anyhow::Error;
type Err = EncodablePackageIdError;

fn from_str(s: &str) -> CargoResult<EncodablePackageId> {
fn from_str(s: &str) -> Result<EncodablePackageId, Self::Err> {
let mut s = s.splitn(3, ' ');
let name = s.next().unwrap();
let version = s.next();
Expand All @@ -674,7 +682,7 @@ impl FromStr for EncodablePackageId {
if let Some(s) = s.strip_prefix('(').and_then(|s| s.strip_suffix(')')) {
Some(EncodableSourceId::new(s.to_string())?)
} else {
anyhow::bail!("invalid serialized PackageId")
return Err(EncodablePackageIdErrorKind::InvalidSerializedPackageId.into());
}
}
None => None,
Expand Down