mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-13 15:24:42 +00:00
* Add craft-aep: After Effects project container and typed view from EffectCraft The .aep (RIFX 'Egg!') and .aepx container as a lossless chunk tree that writes back byte for byte, and the typed, read-only view over it: compositions, layers, properties, keyframes, effects and their settings data, masks, shapes, text documents, markers, cameras, track mattes, footage, project settings and the saving version. Moved from effectcraft crates/aep/src/container at f6b4da0a with its unit tests, the container integration tests, the aepdump and stubicc tools and docs/aep-format.md. The match-name tables (effect_map, style_map), the importer and the exporter are written against EffectCraft's model and stay there. ExtractorChannels::sources takes the caller's name for a copied channel instead of an EffectCraft constant. * craft-aep: read the Photoshop layer a footage item shows A footage item made from one layer of a .psd stores the layer in its `opti` (tag `8BPS`): the layer record's index (big-endian i32 at 14, -1 for the merged image), the document's two sides (little-endian u32 at 32 and 36), the layer's bounds (little-endian i32 at 78, 82, 86, 90) and its name (UTF-8 from 344). `Footage::psd_layer` reads them as `PsdLayer`. The format part of storytold/effectcraft#3449; the importer's use of it stays in EffectCraft. --------- Co-authored-by: arnav-hiwarkar <asharnav2008@gmail.com>
58 lines
2.7 KiB
Rust
58 lines
2.7 KiB
Rust
//! Errors of the container reader and writer.
|
|
|
|
use std::fmt;
|
|
|
|
/// Why a file could not be read or written.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum AepError {
|
|
/// The input is shorter than the 12-byte `RIFX` header, or does not start with `RIFX`.
|
|
NotRifx,
|
|
/// The form type after the declared size is not `Egg!`.
|
|
BadFormType([u8; 4]),
|
|
/// The declared container size runs past the end of the input.
|
|
Truncated { declared: u64, available: u64 },
|
|
/// A chunk declares more body bytes than remain in its parent (`offset` is the chunk header).
|
|
ChunkTooLarge { offset: usize, size: u64, available: u64 },
|
|
/// The chunk structure is not well formed at `offset` (what is wrong is in `what`).
|
|
Malformed { offset: usize, what: &'static str },
|
|
/// Nesting is deeper than the allowed maximum.
|
|
TooDeep,
|
|
/// More chunks than the allowed maximum.
|
|
TooManyChunks,
|
|
/// A chunk or the whole file would not fit the 32-bit size fields when writing.
|
|
TooLarge,
|
|
/// An `.aepx` is not well-formed XML of the subset After Effects writes, at byte `offset`
|
|
/// (what is wrong is in `what`).
|
|
Xml { offset: usize, what: &'static str },
|
|
}
|
|
|
|
impl AepError {
|
|
/// Structural problems of the input that a lenient caller may repair by keeping a body opaque;
|
|
/// limits (`TooDeep`, `TooManyChunks`) are never repaired.
|
|
pub(crate) fn is_structural(&self) -> bool {
|
|
matches!(self, Self::ChunkTooLarge { .. } | Self::Malformed { .. } | Self::Truncated { .. })
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for AepError {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::NotRifx => write!(f, "not an After Effects project: no RIFX header"),
|
|
Self::BadFormType(t) => write!(f, "RIFX form type {:?} is not \"Egg!\"", String::from_utf8_lossy(t)),
|
|
Self::Truncated { declared, available } => {
|
|
write!(f, "truncated file: the container declares {declared} bytes, {available} are available")
|
|
}
|
|
Self::ChunkTooLarge { offset, size, available } => {
|
|
write!(f, "chunk at offset {offset} declares {size} bytes, only {available} remain")
|
|
}
|
|
Self::Malformed { offset, what } => write!(f, "malformed chunk structure at offset {offset}: {what}"),
|
|
Self::TooDeep => write!(f, "chunks are nested too deeply"),
|
|
Self::TooManyChunks => write!(f, "too many chunks"),
|
|
Self::TooLarge => write!(f, "chunk too large for the 32-bit size field"),
|
|
Self::Xml { offset, what } => write!(f, "not a readable After Effects XML project (.aepx): {what} at byte {offset}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for AepError {}
|