-
Notifications
You must be signed in to change notification settings - Fork 6
feat: add method to parse image from fsuri, like btcfs, ipfs and ckbfs #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
a299979
37bdec4
594a474
f4baebc
446b126
a9df851
9632287
b94e031
36c84ac
6666e23
232bb07
9b21c08
1762716
18fbb92
0d97f11
2ec1413
2a0e322
be98e33
f1fea14
d74fcc1
b80581d
e14a327
e37f5fa
c851382
f1e138b
6823344
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -40,13 +40,57 @@ $ RUST_LOG=dob_decoder_server=debug cargo run | |||||
|
|
||||||
| And then, try it out: | ||||||
|
|
||||||
| **Get protocol versions:** | ||||||
|
|
||||||
| ```bash | ||||||
| $ curl -H 'content-type: application/json' -d '{ | ||||||
| "id": 1, | ||||||
| "jsonrpc": "2.0", | ||||||
| "method": "dob_protocol_version", | ||||||
| "params": [] | ||||||
| }' http://localhost:8090 | ||||||
| ``` | ||||||
|
|
||||||
| **Decode a spore ID:** | ||||||
|
|
||||||
| ```bash | ||||||
| $ echo '{ | ||||||
| "id": 2, | ||||||
| "jsonrpc": "2.0", | ||||||
| "method": "dob_decode", | ||||||
| "params": [ | ||||||
| "<spore_id in hex format without 0x prefix>" | ||||||
| "4f7fb83a65dae9b95c21e55d5776a84f17bb6377681befeedb20a077ce1d8aad" | ||||||
| ] | ||||||
| }' \ | ||||||
| | curl -H 'content-type: application/json' -d @- \ | ||||||
| http://localhost:8090 | ||||||
| ``` | ||||||
|
|
||||||
| **Decode and extract SVG from another example spore ID on mainnet:** | ||||||
|
|
||||||
| ```bash | ||||||
| $ echo '{ | ||||||
| "id": 3, | ||||||
| "jsonrpc": "2.0", | ||||||
| "method": "dob_decode_svg", | ||||||
| "params": [ | ||||||
| "0x577bf0de0dcffe2811fa827480a700bc800c8e1e9606615b1484baeea2cba830" | ||||||
| ] | ||||||
| }' \ | ||||||
| | curl -H 'content-type: application/json' -d @- \ | ||||||
| http://localhost:8090 | ||||||
| ``` | ||||||
|
Comment on lines
+69
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
|
|
||||||
| **Extract image from a btcfs or ipfs path:** | ||||||
|
|
||||||
| ```bash | ||||||
| $ echo '{ | ||||||
| "id": 4, | ||||||
| "jsonrpc": "2.0", | ||||||
| "method": "dob_extract_image_from_fsuri", | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The RPC method name in this example is incorrect. The implementation in
Suggested change
|
||||||
| "params": [ | ||||||
| "btcfs://5895004e95c8a4b80f05f5314d310067a703134515d82effc2ec6eba0dda3fc9i0", | ||||||
| "base64" | ||||||
| ] | ||||||
| }' \ | ||||||
| | curl -H 'content-type: application/json' -d @- \ | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,3 +1,4 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::collections::HashMap; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::future::Future; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::pin::Pin; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::sync::atomic::{AtomicU64, Ordering}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -9,7 +10,9 @@ use ckb_jsonrpc_types::{ | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| use ckb_sdk::rpc::ckb_indexer::{Cell, Order, Pagination, SearchKey, Tx}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use ckb_types::H256; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use jsonrpc_core::futures::FutureExt; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use lazy_regex::{regex, regex_replace_all}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use reqwest::{Client, Url}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use serde_json::Value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::types::Error; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -150,3 +153,166 @@ impl RpcClient { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| .boxed() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Clone)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct ImageFetchClient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_url: HashMap<String, Url>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl ImageFetchClient { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn new(base_url: &HashMap<String, Url>) -> Self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_url: base_url.clone(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub async fn fetch_images(&self, images_uri: &[String]) -> Result<Vec<Vec<u8>>, Error> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut requests = vec![]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for uri in images_uri { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match uri.try_into()? { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| URI::BTCFS(tx_hash, index) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let url = self | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .base_url | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get("btcfs") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or(Error::FsuriNotFoundInConfig)? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .join(&tx_hash) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .expect("image url"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using
Suggested change
Comment on lines
+178
to
+179
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requests.push(parse_image_from_btcfs(url, index).boxed()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| URI::IPFS(cid) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let url = self | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .base_url | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get("ipfs") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or(Error::FsuriNotFoundInConfig)? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .join(&cid) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .expect("image url"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+178
to
+188
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using
Suggested change
Comment on lines
+187
to
+188
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requests.push( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async move { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let image = reqwest::get(url.clone()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map_err(|e| Error::FetchFromIpfsError(e.to_string()))? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .bytes() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map_err(|e| Error::FetchFromIpfsError(e.to_string()))? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .to_vec(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(image) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .boxed(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut images = vec![]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let responses = futures::future::join_all(requests).await; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for response in responses { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| images.push(response?); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(images) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[allow(clippy::upper_case_acronyms)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| enum URI { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BTCFS(String, usize), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IPFS(String), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl TryFrom<&String> for URI { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type Error = Error; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn try_from(uri: &String) -> Result<Self, Error> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(body) = uri.strip_prefix("btcfs://") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let parts: Vec<&str> = body.split('i').collect::<Vec<_>>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if parts.len() != 2 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(Error::InvalidOnchainFsuriFormat); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let tx_hash = parts[0].to_string(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let index = parts[1] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .parse() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map_err(|_| Error::InvalidOnchainFsuriFormat)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(URI::BTCFS(tx_hash, index)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if let Some(body) = uri.strip_prefix("ipfs://") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let hash = body.to_string(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(URI::IPFS(hash)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Err(Error::InvalidOnchainFsuriFormat) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+220
to
+240
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async fn parse_image_from_btcfs(url: Url, index: usize) -> Result<Vec<u8>, Error> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // parse btc transaction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let btc_tx = reqwest::get(url) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map_err(|e| Error::FetchFromBtcNodeError(e.to_string()))? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .json::<Value>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map_err(|e| Error::FetchFromBtcNodeError(e.to_string()))?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let vin = btc_tx | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get("vin") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or(Error::InvalidBtcTransactionFormat( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "vin not found".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .as_array() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or(Error::InvalidBtcTransactionFormat( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "vin not an array".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .first() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or(Error::InvalidBtcTransactionFormat( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "vin is empty".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let witness = vin | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get("inner_witnessscript_asm") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or(Error::InvalidBtcTransactionFormat( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "inner_witnessscript_asm not found".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .as_str() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or(Error::InvalidBtcTransactionFormat( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "inner_witnessscript_asm not a string".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .to_owned(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // parse inscription body | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut images = vec![]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut witness_view = witness.as_str(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // flexible header pattern, e.g. OP_IF OP_PUSHBYTES_3 444f42 OP_PUSHBYTES_1 01 OP_PUSHBYTES_9 696d6167652f706e67 OP_0 OP_PUSHDATA2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // note: arbitrary part is the specification of image type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let header_pattern = regex!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r#"OP_IF\s+OP_PUSHBYTES_3\s+444f42\s+OP_PUSHBYTES_1\s+01\s+OP_PUSHBYTES_(\d+)\s+([0-9a-fA-F]+)\s+OP_0\s+OP_PUSHDATA2\s+"# | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+281
to
+283
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The regex |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| while let (Some(start), Some(end)) = (witness_view.find("OP_IF"), witness_view.find("OP_ENDIF")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if start >= end { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(Error::InvalidInscriptionFormat( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "bad start and end position".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+285
to
+291
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current logic for finding inscription envelopes uses To fix this, consider implementing a more robust parsing mechanism, such as a stack-based approach, to correctly identify matching |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let inscription = &witness_view[start..end + "OP_ENDIF".len()]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Some(captures) = header_pattern.captures(inscription) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let matched_header = &captures[0]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let base_removed = inscription.replace(matched_header, ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let hexed = regex_replace_all!(r#"\s?OP\_\w+\s?"#, &base_removed, ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let image = hex::decode(hexed.as_bytes()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map_err(|_| Error::InvalidInscriptionContentHexFormat)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| images.push(image); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+294
to
+301
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The regex for the inscription header captures the content type of the inscription, but this information is not used. The |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(Error::InvalidInscriptionFormat( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "HEADER pattern not found".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| witness_view = &witness_view[end + "OP_ENDIF".len()..]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if images.is_empty() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(Error::EmptyInscriptionContent); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let image = images | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get(index) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .cloned() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ok_or(Error::ExceededInscriptionIndex)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(image) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation has been updated to include an example for a
dob_decode_svgmethod. However, the pull request description states that this method was purged, and I can't find its implementation in the new code. This is confusing for users. Please remove this example from the README to align the documentation with the actual implementation.