factor out helper for parsing media keys

Leaving this private in `database::key_value::media` because the way
the metadata is encoded in media keys is a mess. I want to fix that in
the future, and want to limit the number of things that rely on it for
now.
This commit is contained in:
Benjamin Lee 2024-09-14 20:11:29 -07:00
parent 3bb4a25c1d
commit e2cba15ed2
No known key found for this signature in database
GPG key ID: FB9624E2885D55A4

View file

@ -9,6 +9,82 @@ use crate::{
utils, Error, Result,
};
struct MediaFileKeyParts {
mxc: OwnedMxcUri,
width: u32,
height: u32,
meta: FileMeta,
}
impl TryFrom<&MediaFileKey> for MediaFileKeyParts {
type Error = Error;
fn try_from(key: &MediaFileKey) -> Result<MediaFileKeyParts> {
let mut parts = key.as_bytes().split(|&b| b == 0xFF);
let mxc_bytes = parts
.next()
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?;
let mxc = utils::string_from_bytes(mxc_bytes)
.map_err(|_| {
Error::bad_database("Media MXC URI in db is invalid unicode.")
})?
.into();
let thumbnail_size_bytes = parts
.next()
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?;
let thumbnail_size_bytes: &[u8; 8] =
thumbnail_size_bytes.try_into().map_err(|_| {
Error::bad_database("Media ID thumbnail size in db is invalid")
})?;
let width = u32::from_be_bytes(
thumbnail_size_bytes[..4].try_into().expect("should be 4 bytes"),
);
let height = u32::from_be_bytes(
thumbnail_size_bytes[4..].try_into().expect("should be 4 bytes"),
);
let content_type = parts
.next()
.map(|bytes| {
utils::string_from_bytes(bytes).map_err(|_| {
Error::bad_database(
"Content type in mediaid_file is invalid unicode.",
)
})
})
.transpose()?;
let content_disposition_bytes = parts
.next()
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?;
let content_disposition = if content_disposition_bytes.is_empty() {
None
} else {
Some(utils::string_from_bytes(content_disposition_bytes).map_err(
|_| {
Error::bad_database(
"Content Disposition in mediaid_file is invalid \
unicode.",
)
},
)?)
};
Ok(MediaFileKeyParts {
mxc,
width,
height,
meta: FileMeta {
content_disposition,
content_type,
},
})
}
}
impl service::media::Data for KeyValueDatabase {
fn create_file_metadata(
&self,
@ -61,42 +137,7 @@ impl service::media::Data for KeyValueDatabase {
)?;
let key = MediaFileKey::new(key);
let mut parts = key.as_bytes().rsplit(|&b| b == 0xFF);
let content_type = parts
.next()
.map(|bytes| {
utils::string_from_bytes(bytes).map_err(|_| {
Error::bad_database(
"Content type in mediaid_file is invalid unicode.",
)
})
})
.transpose()?;
let content_disposition_bytes = parts
.next()
.ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?;
let content_disposition = if content_disposition_bytes.is_empty() {
None
} else {
Some(utils::string_from_bytes(content_disposition_bytes).map_err(
|_| {
Error::bad_database(
"Content Disposition in mediaid_file is invalid \
unicode.",
)
},
)?)
};
Ok((
FileMeta {
content_disposition,
content_type,
},
key,
))
let parts = MediaFileKeyParts::try_from(&key)?;
Ok((parts.meta, key))
}
}