Skip to content

Commit

Permalink
Support more image types (ordinals#1020)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Dec 20, 2022
1 parent 14f8b3f commit 2825c48
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 21 deletions.
26 changes: 10 additions & 16 deletions src/inscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use {
std::{iter::Peekable, str},
};

mod content_type;

const PROTOCOL_ID: &[u8] = b"ord";

const CONTENT_TAG: &[u8] = &[];
Expand Down Expand Up @@ -47,21 +49,13 @@ impl Inscription {
}
}

let content_type = match path
.extension()
.ok_or_else(|| anyhow!("file must have extension"))?
.to_str()
.ok_or_else(|| anyhow!("unrecognized extension"))?
{
"txt" => "text/plain;charset=utf-8",
"png" => "image/png",
"gif" => "image/gif",
other => {
return Err(anyhow!(
"unrecognized file extension `.{other}`, only .txt, .png and .gif accepted"
))
}
};
let content_type = content_type::for_extension(
path
.extension()
.ok_or_else(|| anyhow!("file must have extension"))?
.to_str()
.ok_or_else(|| anyhow!("unrecognized extension"))?,
)?;

Ok(Self {
content: Some(content),
Expand Down Expand Up @@ -96,7 +90,7 @@ impl Inscription {

match self.content_type()? {
"text/plain;charset=utf-8" => Some(Content::Text(str::from_utf8(content).ok()?)),
"image/png" | "image/gif" => Some(Content::Image),
content_type if content_type::is_image(content_type) => Some(Content::Image),
_ => None,
}
}
Expand Down
58 changes: 58 additions & 0 deletions src/inscription/content_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use super::*;

const TABLE: &[(&str, bool, &[&str])] = &[
("image/apng", true, &["apng"]),
("image/gif", true, &["gif"]),
("image/jpeg", true, &["jpg", "jpeg"]),
("image/png", true, &["png"]),
("image/webp", true, &["webp"]),
("text/plain;charset=utf-8", false, &["txt"]),
];

lazy_static! {
static ref IMAGE_CONTENT_TYPES: HashSet<&'static str> = TABLE
.iter()
.filter(|(_, image, _)| *image)
.map(|(content_type, _, _)| *content_type)
.collect();
}

pub(crate) fn is_image(content_type: &str) -> bool {
IMAGE_CONTENT_TYPES.contains(content_type)
}

pub(crate) fn for_extension(extension: &str) -> Result<&'static str, Error> {
for (content_type, _, extensions) in TABLE {
if extensions.contains(&extension) {
return Ok(content_type);
}
}

Err(anyhow!(
"unsupported file extension `.{extension}`, supported extensions: {}",
TABLE
.iter()
.map(|(_, _, extensions)| extensions[0])
.collect::<Vec<&str>>()
.join(" "),
))
}

#[cfg(test)]
mod tests {
#[test]
fn is_image() {
assert!(super::is_image("image/apng"));
assert!(!super::is_image("foo"));
}

#[test]
fn for_extension() {
assert_eq!(super::for_extension("jpg").unwrap(), "image/jpeg");
assert_eq!(super::for_extension("jpeg").unwrap(), "image/jpeg");
assert_eq!(
super::for_extension("foo").unwrap_err().to_string(),
"unsupported file extension `.foo`, supported extensions: apng gif jpg png webp txt"
);
}
}
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ use {
clap::{ArgGroup, Parser},
derive_more::{Display, FromStr},
html_escaper::{Escape, Trusted},
lazy_static::lazy_static,
regex::Regex,
serde::{Deserialize, Serialize},
std::{
cmp::Ordering,
collections::{BTreeMap, VecDeque},
collections::{BTreeMap, HashSet, VecDeque},
env,
fmt::{self, Display, Formatter},
fs, io,
Expand Down
1 change: 0 additions & 1 deletion src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use {
Router,
},
axum_server::Handle,
lazy_static::lazy_static,
rust_embed::RustEmbed,
rustls_acme::{
acme::{LETS_ENCRYPT_PRODUCTION_DIRECTORY, LETS_ENCRYPT_STAGING_DIRECTORY},
Expand Down
6 changes: 3 additions & 3 deletions tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ fn inscribe_unknown_file_extension() {
let txid = rpc_server.mine_blocks(1)[0].txdata[0].txid();

CommandBuilder::new(format!(
"--chain regtest wallet inscribe --satpoint {txid}:0:0 --file pepe.jpg"
"--chain regtest wallet inscribe --satpoint {txid}:0:0 --file pepe.xyz"
))
.write("pepe.jpg", [1; 520])
.write("pepe.xyz", [1; 520])
.rpc_server(&rpc_server)
.expected_exit_code(1)
.expected_stderr("error: unrecognized file extension `.jpg`, only .txt, .png and .gif accepted\n")
.stderr_regex(r"error: unsupported file extension `\.xyz`, supported extensions: apng .*\n")
.run();
}

Expand Down

0 comments on commit 2825c48

Please sign in to comment.