diff --git a/.github/workflows/ci-sdk.yaml b/.github/workflows/ci-sdk.yaml index 3a68e4d993..ee6398ee1f 100644 --- a/.github/workflows/ci-sdk.yaml +++ b/.github/workflows/ci-sdk.yaml @@ -68,7 +68,7 @@ jobs: - name: Clippy run: cargo clippy --all-features - name: Unused Dependencies - run: cargo +nightly-2022-02-08 udeps + run: cargo +nightly udeps - name: Additional per-crate checks run: ../tools/additional-per-crate-checks.sh ./sdk/ ../tools/ci-cdk/ env: @@ -87,7 +87,7 @@ jobs: default: true - uses: actions-rs/toolchain@v1 with: - toolchain: nightly-2022-02-08 + toolchain: nightly default: false - name: Cache cargo bin uses: actions/cache@v2 @@ -97,11 +97,15 @@ jobs: - name: Install additional cargo binaries run: | if [[ ! -f ~/.cargo/bin/cargo-udeps ]]; then - cargo +nightly-2022-02-08 install cargo-udeps + cargo +nightly install cargo-udeps fi if [[ ! -f ~/.cargo/bin/cargo-hack ]]; then cargo install cargo-hack fi + # Install the api-linter tool for finding external types in public APIs + pushd tools/api-linter &>/dev/null + cargo install --debug --path . + popd &>/dev/null - name: Generate a name for the SDK id: gen-name run: echo "name=${GITHUB_REF##*/}" >> $GITHUB_ENV diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 72d79628e7..5c328bc56d 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -10,3 +10,9 @@ # references = ["smithy-rs#920"] # meta = { "breaking" = false, "tada" = false, "bug" = false } # author = "rcoh" + +[[smithy-rs]] +message = "`aws_smithy_types::primitive::Encoder` is now a struct rather than an enum, but its usage remains the same." +references = ["smithy-rs#1209"] +meta = { "breaking" = true, "tada" = false, "bug" = false } +author = "jdisanti" diff --git a/rust-runtime/aws-smithy-types/additional-ci b/rust-runtime/aws-smithy-types/additional-ci new file mode 100755 index 0000000000..fb5a6d69da --- /dev/null +++ b/rust-runtime/aws-smithy-types/additional-ci @@ -0,0 +1,15 @@ +#!/bin/bash +# +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. +# + +# This script contains additional CI checks to run for this specific package + +set -e + +echo "### Checking for duplicate dependency versions in the normal dependency graph with all features enabled" +cargo tree -d --edges normal --all-features + +echo "### Running api-linter" +cargo +nightly api-linter --all-features diff --git a/rust-runtime/aws-smithy-types/src/primitive.rs b/rust-runtime/aws-smithy-types/src/primitive.rs index dcf4c209cf..b32ac438ab 100644 --- a/rust-runtime/aws-smithy-types/src/primitive.rs +++ b/rust-runtime/aws-smithy-types/src/primitive.rs @@ -94,41 +94,26 @@ impl Parse for f64 { } } -/// Primitive Type Encoder -/// -/// Encodes primitive types in Smithy's specified format. For floating-point numbers, -/// Smithy requires that NaN and Infinity values be specially encoded. -/// -/// This type implements `From` for all Smithy primitive types. -#[non_exhaustive] -pub enum Encoder { +enum Inner { /// Boolean - #[non_exhaustive] Bool(bool), /// 8-bit signed integer - #[non_exhaustive] I8(i8, itoa::Buffer), /// 16-bit signed integer - #[non_exhaustive] I16(i16, itoa::Buffer), /// 32-bit signed integer - #[non_exhaustive] I32(i32, itoa::Buffer), /// 64-bit signed integer - #[non_exhaustive] I64(i64, itoa::Buffer), /// 64-bit unsigned integer - #[non_exhaustive] U64(u64, itoa::Buffer), - #[non_exhaustive] /// 32-bit IEEE 754 single-precision floating-point number F32(f32, ryu::Buffer), /// 64-bit IEEE 754 double-precision floating-point number - #[non_exhaustive] F64(f64, ryu::Buffer), } -impl Debug for Encoder { +impl Debug for Inner { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Self::Bool(v) => write!(f, "Bool({})", v), @@ -143,18 +128,28 @@ impl Debug for Encoder { } } +/// Primitive Type Encoder +/// +/// Encodes primitive types in Smithy's specified format. For floating-point numbers, +/// Smithy requires that NaN and Infinity values be specially encoded. +/// +/// This type implements `From` for all Smithy primitive types. +#[non_exhaustive] +#[derive(Debug)] +pub struct Encoder(Inner); + impl Encoder { /// Encodes a Smithy primitive as a string. pub fn encode(&mut self) -> &str { - match self { - Encoder::Bool(true) => "true", - Encoder::Bool(false) => "false", - Encoder::I8(v, buf) => buf.format(*v), - Encoder::I16(v, buf) => buf.format(*v), - Encoder::I32(v, buf) => buf.format(*v), - Encoder::I64(v, buf) => buf.format(*v), - Encoder::U64(v, buf) => buf.format(*v), - Encoder::F32(v, buf) => { + match &mut self.0 { + Inner::Bool(true) => "true", + Inner::Bool(false) => "false", + Inner::I8(v, buf) => buf.format(*v), + Inner::I16(v, buf) => buf.format(*v), + Inner::I32(v, buf) => buf.format(*v), + Inner::I64(v, buf) => buf.format(*v), + Inner::U64(v, buf) => buf.format(*v), + Inner::F32(v, buf) => { if v.is_nan() { float::NAN } else if *v == f32::INFINITY { @@ -165,7 +160,7 @@ impl Encoder { buf.format_finite(*v) } } - Encoder::F64(v, buf) => { + Inner::F64(v, buf) => { if v.is_nan() { float::NAN } else if *v == f64::INFINITY { @@ -182,49 +177,49 @@ impl Encoder { impl From for Encoder { fn from(input: bool) -> Self { - Self::Bool(input) + Self(Inner::Bool(input)) } } impl From for Encoder { fn from(input: i8) -> Self { - Self::I8(input, itoa::Buffer::new()) + Self(Inner::I8(input, itoa::Buffer::new())) } } impl From for Encoder { fn from(input: i16) -> Self { - Self::I16(input, itoa::Buffer::new()) + Self(Inner::I16(input, itoa::Buffer::new())) } } impl From for Encoder { fn from(input: i32) -> Self { - Self::I32(input, itoa::Buffer::new()) + Self(Inner::I32(input, itoa::Buffer::new())) } } impl From for Encoder { fn from(input: i64) -> Self { - Self::I64(input, itoa::Buffer::new()) + Self(Inner::I64(input, itoa::Buffer::new())) } } impl From for Encoder { fn from(input: u64) -> Self { - Self::U64(input, itoa::Buffer::new()) + Self(Inner::U64(input, itoa::Buffer::new())) } } impl From for Encoder { fn from(input: f32) -> Self { - Self::F32(input, ryu::Buffer::new()) + Self(Inner::F32(input, ryu::Buffer::new())) } } impl From for Encoder { fn from(input: f64) -> Self { - Self::F64(input, ryu::Buffer::new()) + Self(Inner::F64(input, ryu::Buffer::new())) } } diff --git a/tools/api-linter/Cargo.lock b/tools/api-linter/Cargo.lock index 9f18de95db..9e1689155f 100644 --- a/tools/api-linter/Cargo.lock +++ b/tools/api-linter/Cargo.lock @@ -112,9 +112,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.0.14" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62" +checksum = "e5f1fea81f183005ced9e59cdb01737ef2423956dac5a6d731b06b2ecfaa3467" dependencies = [ "atty", "bitflags", @@ -129,9 +129,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.0.14" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1132dc3944b31c20dd8b906b3a9f0a5d0243e092d59171414969657ac6aa85" +checksum = "5fd1122e63869df2cb309f449da1ad54a7c6dfeb7c7e6ccd8e0825d9eb93bb72" dependencies = [ "heck", "proc-macro-error", diff --git a/tools/api-linter/Cargo.toml b/tools/api-linter/Cargo.toml index 7815e3659d..d39439db3d 100644 --- a/tools/api-linter/Cargo.toml +++ b/tools/api-linter/Cargo.toml @@ -10,7 +10,7 @@ publish = false [dependencies] anyhow = "1" cargo_metadata = "0.14" -clap = { version = "3", features = ["derive"] } +clap = { version = "3.1", features = ["derive"] } owo-colors = { version = "3", features = ["supports-colors"] } pest = "2" # For pretty error formatting rustdoc-types = "0.6" diff --git a/tools/api-linter/src/main.rs b/tools/api-linter/src/main.rs index b895e0e568..e2c0ff2edb 100644 --- a/tools/api-linter/src/main.rs +++ b/tools/api-linter/src/main.rs @@ -15,6 +15,7 @@ use smithy_rs_tool_common::shell::ShellOperation; use std::fmt; use std::fs; use std::path::PathBuf; +use std::process; use std::str::FromStr; use tracing_subscriber::prelude::*; use tracing_subscriber::EnvFilter; @@ -64,7 +65,7 @@ struct ApiLinterArgs { #[clap(long)] no_default_features: bool, /// Comma delimited list of features to enable in the crate - #[clap(long, use_delimiter = true)] + #[clap(long, use_value_delimiter = true)] features: Option>, /// Path to the Cargo manifest manifest_path: Option, @@ -86,7 +87,29 @@ enum Args { ApiLinter(ApiLinterArgs), } -fn main() -> Result<()> { +enum Error { + ValidationErrors, + Failure(anyhow::Error), +} + +impl From for Error { + fn from(err: anyhow::Error) -> Self { + Error::Failure(err) + } +} + +fn main() { + process::exit(match run_main() { + Ok(_) => 0, + Err(Error::ValidationErrors) => 1, + Err(Error::Failure(err)) => { + println!("{:#}", dbg!(err)); + 2 + } + }) +} + +fn run_main() -> Result<(), Error> { let Args::ApiLinter(args) = Args::parse(); if args.verbose { let filter_layer = EnvFilter::try_from_default_env() @@ -124,14 +147,15 @@ fn main() -> Result<()> { let crate_path = if let Some(manifest_path) = args.manifest_path { cargo_metadata_cmd.manifest_path(&manifest_path); manifest_path - .canonicalize()? + .canonicalize() + .context(here!())? .parent() .expect("parent path") .to_path_buf() } else { - std::env::current_dir()? + std::env::current_dir().context(here!())? }; - let cargo_metadata = cargo_metadata_cmd.exec()?; + let cargo_metadata = cargo_metadata_cmd.exec().context(here!())?; let cargo_features = resolve_features(&cargo_metadata)?; eprintln!("Running rustdoc to produce json doc output..."); @@ -162,6 +186,7 @@ fn main() -> Result<()> { errors.len(), "errors".if_supports_color(Stream::Stdout, |text| text.red()) ); + return Err(Error::ValidationErrors); } } OutputFormat::MarkdownTable => { diff --git a/tools/api-linter/tests/integration_test.rs b/tools/api-linter/tests/integration_test.rs index 450e136d29..0a7b566008 100644 --- a/tools/api-linter/tests/integration_test.rs +++ b/tools/api-linter/tests/integration_test.rs @@ -17,7 +17,10 @@ fn run_with_args(in_path: impl AsRef, args: &[&str]) -> String { cmd.arg(arg); } let output = cmd.output().expect("failed to start cargo-api-linter"); - handle_failure("cargo-api-linter", &output).unwrap(); + match output.status.code() { + Some(1) => { /* expected */ } + _ => handle_failure("cargo-api-linter", &output).unwrap(), + } let (stdout, _) = output_text(&output); stdout }