Skip to content

Commit 6409c85

Browse files
committed
Add TiffValue proxy implementations
We have a fundamental choice here: We could add more proxy implementations for `Vec` and `Box` to follow `&'_ T`, for some types that indirections is clear. Vec and arrays are also both very natural ways of expressing a repeated value. However, passing an allocated value to the interface forces us to drop it inside. We might be able to utilize the allocation for an in-place byteswap in a future increment but not with the current design. So, overall, I think that inherently `Drop`-y types should be avoided in these implementations. Instead, we can use the amazing diagnostic tools in the compiler to just help the users navigate the type system. We can still provide the impl for arrays. For context, see: https://users.rust-lang.org/t/what-type-is-u16/137395 Now they see: | 38 | .write_tag(tiff::tags::Tag::GeoKeyDirectoryTag, &geokey); | ^^^^^^ the trait `TiffValue` is not implemented for `&Vec<u16>` | = 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[..]` = help: the following other types implement trait `TiffValue`: Previously the compiler would both strip the `&` in its first message (due to our forwarding impl) and not list any way of getting a reference-to-slice.
1 parent fe305ec commit 6409c85

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/encoder/tiff_value.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ use crate::{bytecast, tags::Type, TiffError, TiffFormatError, TiffResult};
55
use super::writer::TiffWriter;
66

77
/// Trait for types that can be encoded in a tiff file
8+
#[diagnostic::on_unimplemented(
9+
message = "the type `{Self}` does not implement `TiffValue`",
10+
note = "the trait is implemented for primitive types (`u8`, `i16`, `f32`, etc.)",
11+
note = "the trait is implemented for shared references to values",
12+
note = "the trait is implemented for slices, pass them by reference (e.g. `&[u8]`)",
13+
note = "the trait is implemented for arrays if it is implemented for a slice",
14+
note = "values in a `Vec` or `Box` should be dereferenced, e.g. `&vec[..]`",
15+
)]
816
pub trait TiffValue {
917
const BYTE_LEN: u8;
1018
const FIELD_TYPE: Type;
@@ -450,6 +458,14 @@ impl TiffValue for str {
450458
}
451459
}
452460

461+
// If you pass `&Vec<_>` then you'd get at first sight the complaint:
462+
//
463+
// `Vec<T>` does not implement `TiffValue`
464+
//
465+
// and a list of implementations of `TiffValue` that are quite unrelated. That is not very helpful.
466+
// We do not *want* `Vec` to implement the trait as an owning type, instead you should pass a
467+
// reference to a slice. The error message is further customized in the diagnostics of the trait.
468+
#[diagnostic::do_not_recommend]
453469
impl<T: TiffValue + ?Sized> TiffValue for &'_ T {
454470
const BYTE_LEN: u8 = T::BYTE_LEN;
455471
const FIELD_TYPE: Type = T::FIELD_TYPE;
@@ -467,6 +483,27 @@ impl<T: TiffValue + ?Sized> TiffValue for &'_ T {
467483
}
468484
}
469485

486+
/// An array is treated like a slice of the same length.
487+
impl<T, const N: usize> TiffValue for [T; N]
488+
where
489+
[T]: TiffValue,
490+
{
491+
const BYTE_LEN: u8 = <[T]>::BYTE_LEN;
492+
const FIELD_TYPE: Type = <[T]>::FIELD_TYPE;
493+
494+
fn count(&self) -> usize {
495+
self.as_slice().count()
496+
}
497+
498+
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
499+
self.as_slice().write(writer)
500+
}
501+
502+
fn data(&self) -> Cow<'_, [u8]> {
503+
self.as_slice().data()
504+
}
505+
}
506+
470507
macro_rules! impl_tiff_value_for_contiguous_sequence {
471508
($inner_type:ty; $bytes:expr; $field_type:expr) => {
472509
impl $crate::encoder::TiffValue for [$inner_type] {

0 commit comments

Comments
 (0)