|
1 | 1 | use std::{borrow::Cow, io::Write, slice::from_ref}; |
2 | 2 |
|
3 | | -use crate::{bytecast, tags::Type, TiffError, TiffFormatError, TiffResult}; |
| 3 | +use crate::{bytecast, tags, tags::Type, TiffError, TiffFormatError, TiffResult}; |
4 | 4 |
|
5 | 5 | use super::writer::TiffWriter; |
6 | 6 |
|
@@ -458,6 +458,128 @@ impl TiffValue for str { |
458 | 458 | } |
459 | 459 | } |
460 | 460 |
|
| 461 | +// FIXME: held up on reading the discriminant for all but the unknown variant. |
| 462 | +// |
| 463 | +// It needs to have `repr(u16)` to have a defined layout and then we may read the tag from its |
| 464 | +// value representation by casting a u16 pointer to a pointer to the enum type. |
| 465 | +// unsafe { *<*const _>::from(self).cast::<u16>() } |
| 466 | +// But that is quite unsafe and needs careful review to maintain the safety requirements. Maybe we |
| 467 | +// could get `bytemuck` to add a trait for this (it has `TransparentWrapper`) with a derive for |
| 468 | +// enum types that have an explicit repr. |
| 469 | +// |
| 470 | +// This would allow returning borrowed data in more cases. For all types without an unknown, in all |
| 471 | +// cases including as slices, and for all types with and unknown variant when we have a single |
| 472 | +// value (either returning a borrowed discriminant or a borrowed value within `Unknown`). |
| 473 | +impl TiffValue for tags::CompressionMethod { |
| 474 | + const BYTE_LEN: u8 = <u16 as TiffValue>::BYTE_LEN; |
| 475 | + const FIELD_TYPE: Type = Type::SHORT; |
| 476 | + |
| 477 | + fn count(&self) -> usize { |
| 478 | + 1 |
| 479 | + } |
| 480 | + |
| 481 | + fn data(&self) -> Cow<'_, [u8]> { |
| 482 | + let bytes = self.to_u16().to_ne_bytes(); |
| 483 | + Cow::Owned(bytes.to_vec()) |
| 484 | + } |
| 485 | +} |
| 486 | + |
| 487 | +impl TiffValue for tags::PhotometricInterpretation { |
| 488 | + const BYTE_LEN: u8 = <u16 as TiffValue>::BYTE_LEN; |
| 489 | + const FIELD_TYPE: Type = Type::SHORT; |
| 490 | + |
| 491 | + fn count(&self) -> usize { |
| 492 | + 1 |
| 493 | + } |
| 494 | + |
| 495 | + fn data(&self) -> Cow<'_, [u8]> { |
| 496 | + self.to_u16().to_ne_bytes().to_vec().into() |
| 497 | + } |
| 498 | +} |
| 499 | + |
| 500 | +impl TiffValue for tags::PlanarConfiguration { |
| 501 | + const BYTE_LEN: u8 = 2; |
| 502 | + const FIELD_TYPE: Type = Type::SHORT; |
| 503 | + |
| 504 | + fn count(&self) -> usize { |
| 505 | + 1 |
| 506 | + } |
| 507 | + |
| 508 | + fn data(&self) -> Cow<'_, [u8]> { |
| 509 | + self.to_u16().to_ne_bytes().to_vec().into() |
| 510 | + } |
| 511 | +} |
| 512 | + |
| 513 | +impl TiffValue for tags::Predictor { |
| 514 | + const BYTE_LEN: u8 = <u16 as TiffValue>::BYTE_LEN; |
| 515 | + const FIELD_TYPE: Type = Type::SHORT; |
| 516 | + |
| 517 | + fn count(&self) -> usize { |
| 518 | + 1 |
| 519 | + } |
| 520 | + |
| 521 | + fn data(&self) -> Cow<'_, [u8]> { |
| 522 | + self.to_u16().to_ne_bytes().to_vec().into() |
| 523 | + } |
| 524 | +} |
| 525 | + |
| 526 | +impl TiffValue for tags::ResolutionUnit { |
| 527 | + const BYTE_LEN: u8 = <u16 as TiffValue>::BYTE_LEN; |
| 528 | + const FIELD_TYPE: Type = Type::SHORT; |
| 529 | + |
| 530 | + fn count(&self) -> usize { |
| 531 | + 1 |
| 532 | + } |
| 533 | + |
| 534 | + fn data(&self) -> Cow<'_, [u8]> { |
| 535 | + self.to_u16().to_ne_bytes().to_vec().into() |
| 536 | + } |
| 537 | +} |
| 538 | + |
| 539 | +/// This is implemented for slices as the `SampleFormat` tag takes a count of `N`. |
| 540 | +/// |
| 541 | +/// Use `core::slice::from_ref` if you really need to write a single element. |
| 542 | +/// |
| 543 | +/// See: <https://web.archive.org/web/20191120220815/https://www.awaresystems.be/imaging/tiff/tifftags/sampleformat.html> |
| 544 | +impl TiffValue for [tags::SampleFormat] { |
| 545 | + const BYTE_LEN: u8 = <u16 as TiffValue>::BYTE_LEN; |
| 546 | + const FIELD_TYPE: Type = Type::SHORT; |
| 547 | + |
| 548 | + fn count(&self) -> usize { |
| 549 | + self.len() |
| 550 | + } |
| 551 | + |
| 552 | + fn data(&self) -> Cow<'_, [u8]> { |
| 553 | + let mut buf: Vec<u8> = Vec::with_capacity(self.len() * 2); |
| 554 | + for x in self { |
| 555 | + buf.extend_from_slice(&x.to_u16().to_ne_bytes()); |
| 556 | + } |
| 557 | + Cow::Owned(buf) |
| 558 | + } |
| 559 | +} |
| 560 | + |
| 561 | +/// This is implemented for slices as the `ExtraSamples` tag takes a count of `N`. |
| 562 | +/// |
| 563 | +/// Use `core::slice::from_ref` if you really need to write a single element. |
| 564 | +/// |
| 565 | +/// See: <https://web.archive.org/web/20191120220815/https://www.awaresystems.be/imaging/tiff/tifftags/extrasamples.html> |
| 566 | +impl TiffValue for [tags::ExtraSamples] { |
| 567 | + const BYTE_LEN: u8 = <u16 as TiffValue>::BYTE_LEN; |
| 568 | + const FIELD_TYPE: Type = Type::SHORT; |
| 569 | + |
| 570 | + fn count(&self) -> usize { |
| 571 | + self.len() |
| 572 | + } |
| 573 | + |
| 574 | + fn data(&self) -> Cow<'_, [u8]> { |
| 575 | + let mut buf: Vec<u8> = Vec::with_capacity(self.len() * 2); |
| 576 | + for x in self { |
| 577 | + buf.extend_from_slice(&x.to_u16().to_ne_bytes()); |
| 578 | + } |
| 579 | + Cow::Owned(buf) |
| 580 | + } |
| 581 | +} |
| 582 | + |
461 | 583 | // If you pass `&Vec<_>` then you'd get at first sight the complaint: |
462 | 584 | // |
463 | 585 | // `Vec<T>` does not implement `TiffValue` |
|
0 commit comments