1use std::fmt;
23use std::io::{self};
24
25pub const HEADER: &[u8; 4] = b"GMAD";
27
28pub const VERSION: i8 = 3;
30
31mod reader;
32pub use reader::read;
33
34mod builder;
35pub use builder::Builder;
36
37#[derive(Clone, Debug, PartialEq, Eq, Default)]
39pub struct GMAFile {
40 pub name: String,
41 pub content: Vec<u8>,
42 pub size: i64,
43}
44
45#[derive(Debug)]
47pub enum GmaError {
48 Io(io::Error),
49 InvalidHeader([u8; 4]),
50 InvalidVersion(i8),
51 MissingNullTerminator, SizeOutOfRange(i64),
53 TrailingMarkerMismatch(u32),
54}
55
56impl fmt::Display for GmaError {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 match self {
59 GmaError::Io(e) => write!(f, "io error: {e}"),
60 GmaError::InvalidHeader(got) => {
61 write!(f, "invalid header: {:?}", String::from_utf8_lossy(got))
62 }
63 GmaError::InvalidVersion(v) => write!(f, "invalid version: {v}"),
64 GmaError::MissingNullTerminator => write!(f, "missing null terminator in C string"),
65 GmaError::SizeOutOfRange(sz) => write!(f, "negative or invalid size: {sz}"),
66 GmaError::TrailingMarkerMismatch(v) => {
67 write!(f, "expected trailing 0 u32 marker, got {v}")
68 }
69 }
70 }
71}
72
73impl std::error::Error for GmaError {
74 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
75 if let GmaError::Io(e) = self {
76 Some(e)
77 } else {
78 None
79 }
80 }
81}
82
83impl From<io::Error> for GmaError {
84 fn from(e: io::Error) -> Self {
85 GmaError::Io(e)
86 }
87}