diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7e087ca..fe3ebab 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -9,14 +9,14 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - rust: ["1.74.0", stable, beta, nightly] + rust: ["1.85.0", stable, beta, nightly] steps: - uses: actions/checkout@v2 - uses: dtolnay/rust-toolchain@nightly - if: ${{ matrix.rust == '1.74.0' }} + if: ${{ matrix.rust == '1.85.0' }} - name: Generate Cargo.lock with minimal-version dependencies - if: ${{ matrix.rust == '1.74.0' }} + if: ${{ matrix.rust == '1.85.0' }} run: cargo -Zminimal-versions generate-lockfile - uses: dtolnay/rust-toolchain@v1 @@ -29,7 +29,7 @@ jobs: - name: build run: cargo build -v - name: test - if: ${{ matrix.rust != '1.74.0' }} + if: ${{ matrix.rust != '1.85.0' }} run: cargo test -v && cargo doc -v features: diff --git a/Cargo.toml b/Cargo.toml index c067ce4..82118fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" resolver = "2" # note: when changed, also update test runner in `.github/workflows/rust.yml` -rust-version = "1.74.0" +rust-version = "1.85.0" license = "MIT" description = "TIFF decoding and encoding library in pure Rust" diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 45024e3..c56c012 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -766,7 +766,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind> ImageEncoder<'a, W, T, } else { let mut sample_format: Vec<_> = ::BITS_PER_SAMPLE.to_vec(); let replicated = - core::iter::repeat(::BITS_PER_SAMPLE[0]).take(self.extra_samples.len()); + core::iter::repeat_n(::BITS_PER_SAMPLE[0], self.extra_samples.len()); sample_format.extend(replicated); self.encoder @@ -788,7 +788,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind> ImageEncoder<'a, W, T, // extra samples and not provided via a slice used for samples themselves. .unwrap_or(SampleFormat::Void.to_u16()); - sample_format.extend(core::iter::repeat(extra_format).take(self.extra_samples.len())); + sample_format.extend(core::iter::repeat_n(extra_format, self.extra_samples.len())); self.encoder .write_tag(Tag::SampleFormat, &sample_format[..])?; diff --git a/src/encoder/tiff_value.rs b/src/encoder/tiff_value.rs index 57d278d..16ab2c1 100644 --- a/src/encoder/tiff_value.rs +++ b/src/encoder/tiff_value.rs @@ -5,6 +5,14 @@ use crate::{bytecast, tags::Type, TiffError, TiffFormatError, TiffResult}; use super::writer::TiffWriter; /// Trait for types that can be encoded in a tiff file +#[diagnostic::on_unimplemented( + message = "the type `{Self}` does not implement `TiffValue`", + note = "the trait is implemented for primitive types (`u8`, `i16`, `f32`, etc.)", + note = "the trait is implemented for shared references to values", + note = "the trait is implemented for slices, pass them by reference (e.g. `&[u8]`)", + note = "the trait is implemented for arrays if it is implemented for a slice", + note = "values in a `Vec` or `Box` should be dereferenced, e.g. `&vec[..]`" +)] pub trait TiffValue { const BYTE_LEN: u8; const FIELD_TYPE: Type; @@ -450,6 +458,14 @@ impl TiffValue for str { } } +// If you pass `&Vec<_>` then you'd get at first sight the complaint: +// +// `Vec` does not implement `TiffValue` +// +// and a list of implementations of `TiffValue` that are quite unrelated. That is not very helpful. +// We do not *want* `Vec` to implement the trait as an owning type, instead you should pass a +// reference to a slice. The error message is further customized in the diagnostics of the trait. +#[diagnostic::do_not_recommend] impl TiffValue for &'_ T { const BYTE_LEN: u8 = T::BYTE_LEN; const FIELD_TYPE: Type = T::FIELD_TYPE; @@ -467,6 +483,27 @@ impl TiffValue for &'_ T { } } +/// An array is treated like a slice of the same length. +impl TiffValue for [T; N] +where + [T]: TiffValue, +{ + const BYTE_LEN: u8 = <[T]>::BYTE_LEN; + const FIELD_TYPE: Type = <[T]>::FIELD_TYPE; + + fn count(&self) -> usize { + self.as_slice().count() + } + + fn write(&self, writer: &mut TiffWriter) -> TiffResult<()> { + self.as_slice().write(writer) + } + + fn data(&self) -> Cow<'_, [u8]> { + self.as_slice().data() + } +} + macro_rules! impl_tiff_value_for_contiguous_sequence { ($inner_type:ty; $bytes:expr; $field_type:expr) => { impl $crate::encoder::TiffValue for [$inner_type] {