From e2cba15ed2ec1681cc455d66a7bb2053cc204f23 Mon Sep 17 00:00:00 2001 From: Benjamin Lee Date: Sat, 14 Sep 2024 20:11:29 -0700 Subject: [PATCH] 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. --- src/database/key_value/media.rs | 115 ++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 37 deletions(-) diff --git a/src/database/key_value/media.rs b/src/database/key_value/media.rs index 314cd0a9..1748b360 100644 --- a/src/database/key_value/media.rs +++ b/src/database/key_value/media.rs @@ -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 { + 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)) } }