Optimize binstalk-{manifest, types} (#610)

* Add new dep maybe-owned v0.3.4 to binstalk-types with features serde
* Re-export maybe_owned in binstalk-types
* Optimize `CrateSource::url`: Use `MaybeOwned<'static, Url>`
   to avoid cloning in `CrateSource::cratesio_registry`
* Optimize `Source`: Use `MaybeOwned<'static, Url>`
   to avoid cloning in `Source::cratesio_registry` and
   `impl From<&CrateSource> for Source`.
* Optimize `Source`: Add lifetime `<'a>` to avoid cloning
   in `impl<'a> From<&'a CrateSource> for Source<'a>`
* Optimize `CratesToml::append_to_path`: Avoid cloning
   caused by `CrateVersionSource::from` by manually `format!` name, version
   and source into string.
* Add new dep beef v0.5.2 to binstalk-manifests with features impl_serde
* Optimize `CratesToml::append_to_path`: Eliminate `metadata.bins.clone()` by using `Cow`
* Replace dep toml_edit with toml v0.5.10 in binstalk-manifests
   to speed up compilation and reduce bloat.
   
   Previously we switch to toml_edit because it is unmaintained, but now
   with it moved into toml-rs/toml as a workspace, it is now under active
   maintenance again, thus we switch back to it.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2022-12-21 17:07:04 +11:00 committed by GitHub
parent e519409ad8
commit fef8bb6774
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 67 deletions

View file

@ -10,6 +10,7 @@ edition = "2021"
license = "Apache-2.0 OR MIT"
[dependencies]
beef = { version = "0.5.2", features = ["impl_serde"] }
binstalk-types = { version = "0.1.0", path = "../binstalk-types" }
compact_str = { version = "0.6.1", features = ["serde"] }
fs-lock = { version = "0.1.0", path = "../fs-lock" }
@ -20,7 +21,7 @@ serde = { version = "1.0.151", features = ["derive"] }
serde-tuple-vec-map = "1.0.1"
serde_json = "1.0.91"
thiserror = "1.0.38"
toml_edit = { version = "0.15.0", features = ["easy"] }
toml = "0.5.10"
url = { version = "2.3.1", features = ["serde"] }
[dev-dependencies]

View file

@ -15,6 +15,7 @@ use std::{
path::{Path, PathBuf},
};
use beef::Cow;
use compact_str::CompactString;
use fs_lock::FileLock;
use home::cargo_home;
@ -31,12 +32,12 @@ mod crate_version_source;
use crate_version_source::*;
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct CratesToml {
pub struct CratesToml<'a> {
#[serde(with = "tuple_vec_map")]
v1: Vec<(String, Vec<CompactString>)>,
v1: Vec<(String, Cow<'a, [CompactString]>)>,
}
impl CratesToml {
impl CratesToml<'_> {
pub fn default_path() -> Result<PathBuf, CratesTomlParseError> {
Ok(cargo_home()?.join(".crates.toml"))
}
@ -48,7 +49,7 @@ impl CratesToml {
pub fn load_from_reader<R: io::Read>(mut reader: R) -> Result<Self, CratesTomlParseError> {
let mut vec = Vec::new();
reader.read_to_end(&mut vec)?;
Ok(toml_edit::easy::from_slice(&vec)?)
Ok(toml::from_slice(&vec)?)
}
pub fn load_from_path(path: impl AsRef<Path>) -> Result<Self, CratesTomlParseError> {
@ -59,7 +60,7 @@ impl CratesToml {
/// Only use it when you know that the crate is not in the manifest.
/// Otherwise, you need to call [`CratesToml::remove`] first.
pub fn insert(&mut self, cvs: &CrateVersionSource, bins: Vec<CompactString>) {
self.v1.push((cvs.to_string(), bins));
self.v1.push((cvs.to_string(), Cow::owned(bins)));
}
pub fn remove(&mut self, name: &str) {
@ -75,7 +76,7 @@ impl CratesToml {
}
pub fn write_to_writer<W: io::Write>(&self, mut writer: W) -> Result<(), CratesTomlParseError> {
let data = toml_edit::easy::to_vec(&self)?;
let data = toml::to_vec(&self)?;
writer.write_all(&data)?;
Ok(())
}
@ -108,8 +109,15 @@ impl CratesToml {
};
for metadata in iter {
c1.remove(&metadata.name);
c1.insert(&CrateVersionSource::from(metadata), metadata.bins.clone());
let name = &metadata.name;
let version = &metadata.current_version;
let source = Source::from(&metadata.source);
c1.remove(name);
c1.v1.push((
format!("{name} {version} ({source})"),
Cow::borrowed(&metadata.bins),
));
}
file.rewind()?;
@ -151,10 +159,10 @@ pub enum CratesTomlParseError {
Io(#[from] io::Error),
#[error(transparent)]
TomlParse(#[from] toml_edit::easy::de::Error),
TomlParse(#[from] toml::de::Error),
#[error(transparent)]
TomlWrite(Box<toml_edit::easy::ser::Error>),
TomlWrite(Box<toml::ser::Error>),
#[error(transparent)]
CvsParse(Box<CvsParseError>),
@ -166,8 +174,8 @@ impl From<CvsParseError> for CratesTomlParseError {
}
}
impl From<toml_edit::easy::ser::Error> for CratesTomlParseError {
fn from(e: toml_edit::easy::ser::Error) -> Self {
impl From<toml::ser::Error> for CratesTomlParseError {
fn from(e: toml::ser::Error) -> Self {
CratesTomlParseError::TomlWrite(Box::new(e))
}
}

View file

@ -1,6 +1,6 @@
use std::{borrow::Cow, fmt, str::FromStr};
use binstalk_types::crate_info::cratesio_url;
use binstalk_types::{crate_info::cratesio_url, maybe_owned::MaybeOwned};
use compact_str::CompactString;
use miette::Diagnostic;
use semver::Version;
@ -14,37 +14,45 @@ use crate::crate_info::{CrateInfo, CrateSource, SourceType};
pub struct CrateVersionSource {
pub name: CompactString,
pub version: Version,
pub source: Source,
pub source: Source<'static>,
}
impl From<&CrateInfo> for CrateVersionSource {
fn from(metadata: &CrateInfo) -> Self {
use SourceType::*;
let url = metadata.source.url.clone();
super::CrateVersionSource {
name: metadata.name.clone(),
version: metadata.current_version.clone(),
source: Source::from(&metadata.source),
source: match metadata.source.source_type {
Git => Source::Git(url),
Path => Source::Path(url),
Registry => Source::Registry(url),
},
}
}
}
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
pub enum Source {
Git(Url),
Path(Url),
Registry(Url),
pub enum Source<'a> {
Git(MaybeOwned<'a, Url>),
Path(MaybeOwned<'a, Url>),
Registry(MaybeOwned<'a, Url>),
}
impl Source {
pub fn cratesio_registry() -> Source {
Self::Registry(cratesio_url().clone())
impl Source<'static> {
pub fn cratesio_registry() -> Self {
Self::Registry(MaybeOwned::Borrowed(cratesio_url()))
}
}
impl From<&CrateSource> for Source {
fn from(source: &CrateSource) -> Self {
impl<'a> From<&'a CrateSource> for Source<'a> {
fn from(source: &'a CrateSource) -> Self {
use SourceType::*;
let url = source.url.clone();
let url = MaybeOwned::Borrowed(source.url.as_ref());
match source.source_type {
Git => Self::Git(url),
@ -65,9 +73,9 @@ impl FromStr for CrateVersionSource {
.splitn(2, '+')
.collect::<Vec<_>>()[..]
{
["git", url] => Source::Git(Url::parse(url)?),
["path", url] => Source::Path(Url::parse(url)?),
["registry", url] => Source::Registry(Url::parse(url)?),
["git", url] => Source::Git(Url::parse(url)?.into()),
["path", url] => Source::Path(Url::parse(url)?.into()),
["registry", url] => Source::Registry(Url::parse(url)?.into()),
[kind, arg] => {
return Err(CvsParseError::UnknownSourceType {
kind: kind.to_string().into_boxed_str(),
@ -117,7 +125,7 @@ impl fmt::Display for CrateVersionSource {
}
}
impl fmt::Display for Source {
impl fmt::Display for Source<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Source::Git(url) => write!(f, "git+{url}"),