lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

encode.rs (3695B)


      1 #[cfg(not(feature = "std"))]
      2 use alloc::{
      3     string::{String, ToString},
      4     vec::Vec,
      5 };
      6 
      7 use radroots_event::{
      8     envelope::kind::KIND_PUBLIC_FILE_METADATA,
      9     media::file_metadata::FileMetadata,
     10     tag::name::{
     11         TAG_ALT, TAG_BLURHASH, TAG_DIMENSIONS, TAG_FALLBACK, TAG_MAGNET, TAG_MIME,
     12         TAG_ORIGINAL_SHA256, TAG_SERVICE, TAG_SHA256, TAG_SIZE, TAG_SUMMARY, TAG_URL,
     13     },
     14 };
     15 
     16 use crate::error::EventEncodeError;
     17 use crate::field_helpers::{
     18     push_optional_tag, push_tag, validate_lowercase_hex_64, validate_non_empty_field,
     19 };
     20 use crate::social_helpers::{dimensions_tag, push_thumbnail, validate_http_url};
     21 use radroots_event::wire::Nip01EventWireParts;
     22 
     23 const DEFAULT_KIND: u32 = KIND_PUBLIC_FILE_METADATA;
     24 
     25 pub fn file_metadata_build_tags(
     26     metadata: &FileMetadata,
     27 ) -> Result<Vec<Vec<String>>, EventEncodeError> {
     28     validate_metadata(metadata)?;
     29     let mut tags = Vec::new();
     30     push_tag(&mut tags, TAG_URL, metadata.url.as_str());
     31     push_tag(&mut tags, TAG_MIME, metadata.mime_type.as_str());
     32     push_tag(&mut tags, TAG_SHA256, metadata.sha256.as_str());
     33     push_optional_tag(
     34         &mut tags,
     35         TAG_ORIGINAL_SHA256,
     36         metadata.original_sha256.as_deref(),
     37     );
     38     if let Some(size) = metadata.size {
     39         push_tag(&mut tags, TAG_SIZE, size.to_string());
     40     }
     41     if let Some(dimensions) = metadata.dimensions.as_ref() {
     42         push_tag(&mut tags, TAG_DIMENSIONS, dimensions_tag(dimensions));
     43     }
     44     push_optional_tag(&mut tags, TAG_BLURHASH, metadata.blurhash.as_deref());
     45     if let Some(thumbnails) = metadata.thumbnails.as_ref() {
     46         for thumbnail in thumbnails {
     47             push_thumbnail(&mut tags, thumbnail);
     48         }
     49     }
     50     push_optional_tag(&mut tags, TAG_SUMMARY, metadata.summary.as_deref());
     51     push_optional_tag(&mut tags, TAG_ALT, metadata.alt.as_deref());
     52     push_optional_tag(&mut tags, TAG_FALLBACK, metadata.fallback.as_deref());
     53     push_optional_tag(&mut tags, TAG_MAGNET, metadata.magnet.as_deref());
     54     if let Some(content_hashes) = metadata.content_hashes.as_ref() {
     55         for hash in content_hashes {
     56             push_optional_tag(&mut tags, "i", Some(hash.as_str()));
     57         }
     58     }
     59     if let Some(services) = metadata.services.as_ref() {
     60         for service in services {
     61             push_optional_tag(&mut tags, TAG_SERVICE, Some(service.as_str()));
     62         }
     63     }
     64     Ok(tags)
     65 }
     66 
     67 pub fn to_wire_parts(metadata: &FileMetadata) -> Result<Nip01EventWireParts, EventEncodeError> {
     68     to_wire_parts_with_kind(metadata, DEFAULT_KIND)
     69 }
     70 
     71 pub fn to_wire_parts_with_kind(
     72     metadata: &FileMetadata,
     73     kind: u32,
     74 ) -> Result<Nip01EventWireParts, EventEncodeError> {
     75     if kind != DEFAULT_KIND {
     76         return Err(EventEncodeError::InvalidKind(kind));
     77     }
     78     Ok(Nip01EventWireParts {
     79         kind,
     80         content: metadata.content.clone().unwrap_or_default(),
     81         tags: file_metadata_build_tags(metadata)?,
     82     })
     83 }
     84 
     85 fn validate_metadata(metadata: &FileMetadata) -> Result<(), EventEncodeError> {
     86     validate_http_url(&metadata.url, "url")?;
     87     validate_non_empty_field(&metadata.mime_type, "mime_type")?;
     88     validate_lowercase_hex_64(&metadata.sha256, "sha256")?;
     89     if let Some(hash) = metadata.original_sha256.as_deref() {
     90         validate_lowercase_hex_64(hash, "original_sha256")?;
     91     }
     92     if let Some(dimensions) = metadata.dimensions.as_ref()
     93         && (dimensions.width == 0 || dimensions.height == 0)
     94     {
     95         return Err(EventEncodeError::InvalidField("dimensions"));
     96     }
     97     if let Some(thumbnails) = metadata.thumbnails.as_ref() {
     98         for thumbnail in thumbnails {
     99             validate_http_url(&thumbnail.url, "thumb")?;
    100         }
    101     }
    102     Ok(())
    103 }