Skip to content
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

Create library crate #3077

Merged
merged 16 commits into from
Feb 2, 2024
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ copyright = "The Ord Maintainers"
maintainer = "The Ord Maintainers"

[workspace]
members = [".", "test-bitcoincore-rpc", "crates/*"]
members = [".", "crates/*"]

[dependencies]
anyhow = { version = "1.0.56", features = ["backtrace"] }
Expand Down Expand Up @@ -49,6 +49,7 @@ mime_guess = "2.0.4"
miniscript = "10.0.0"
mp4 = "0.14.0"
ord-bitcoincore-rpc = "0.17.1"
ordinals = { version = "0.0.1", path = "crates/ordinals" }
redb = "1.5.0"
regex = "1.6.0"
reqwest = { version = "0.11.23", features = ["blocking", "json"] }
Expand All @@ -72,7 +73,7 @@ criterion = "0.5.1"
executable-path = "1.0.0"
pretty_assertions = "1.2.1"
reqwest = { version = "0.11.10", features = ["blocking", "brotli", "json"] }
test-bitcoincore-rpc = { path = "test-bitcoincore-rpc" }
test-bitcoincore-rpc = { path = "crates/test-bitcoincore-rpc" }
unindent = "0.2.1"

[[bench]]
Expand Down
17 changes: 17 additions & 0 deletions crates/ordinals/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "ordinals"
version = "0.0.1"
edition = "2021"
description = "Library for interoperating with ordinals and inscriptions"
homepage = "https://github.com/ordinals/ord"
repository = "https://github.com/ordinals/ord"
license = "CC0-1.0"
rust-version = "1.67"

[dependencies]
serde = { version = "1.0.137", features = ["derive"] }
bitcoin = { version = "0.30.1", features = ["rand"] }
thiserror = "1.0.56"

[dev-dependencies]
serde_json = { version = "1.0.81", features = ["preserve_order"] }
44 changes: 44 additions & 0 deletions crates/ordinals/src/deserialize_from_str.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use super::*;

pub struct DeserializeFromStr<T: FromStr>(pub T);

impl<'de, T: FromStr> DeserializeFromStr<T>
where
T::Err: Display,
{
pub fn with<D>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::<T>::deserialize(deserializer)?.0)
}
}

impl<'de, T: FromStr> Deserialize<'de> for DeserializeFromStr<T>
where
T::Err: Display,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(Self(
FromStr::from_str(&String::deserialize(deserializer)?).map_err(serde::de::Error::custom)?,
))
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn deserialize_from_str() {
assert_eq!(
serde_json::from_str::<DeserializeFromStr<u64>>("\"1\"")
.unwrap()
.0,
1,
);
}
}
23 changes: 23 additions & 0 deletions crates/ordinals/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//! Types for interoperating with ordinals and inscriptions.

use {
bitcoin::{
consensus::{Decodable, Encodable},
OutPoint,
},
serde::{Deserialize, Deserializer, Serialize, Serializer},
std::{
fmt::{self, Display, Formatter},
io,
str::FromStr,
},
thiserror::Error,
};

pub use sat_point::SatPoint;

#[doc(hidden)]
pub use self::deserialize_from_str::DeserializeFromStr;

mod deserialize_from_str;
mod sat_point;
65 changes: 57 additions & 8 deletions src/sat_point.rs → crates/ordinals/src/sat_point.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
use super::*;

use {super::*, bitcoin::transaction::ParseOutPointError, std::num::ParseIntError};

/// A satpoint identifies the location of a sat in an output.
///
/// The string representation of a satpoint consists of that of an outpoint,
/// which identifies and output, followed by `:OFFSET`. For example, the string
/// representation of the first sat of the genesis block coinbase output is
/// `000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f:0:0`,
/// that of the second sat of the genesis block coinbase output is
/// `000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f:0:1`, and
/// so on and so on.
#[derive(Debug, PartialEq, Copy, Clone, Eq, PartialOrd, Ord, Default)]
pub struct SatPoint {
pub outpoint: OutPoint,
Expand Down Expand Up @@ -44,29 +53,69 @@ impl<'de> Deserialize<'de> for SatPoint {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

impl FromStr for SatPoint {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let (outpoint, offset) = s
.rsplit_once(':')
.ok_or_else(|| anyhow!("invalid satpoint: {s}"))?;
let (outpoint, offset) = s.rsplit_once(':').ok_or_else(|| Error::Colon(s.into()))?;

Ok(SatPoint {
outpoint: outpoint.parse()?,
offset: offset.parse()?,
outpoint: outpoint
.parse::<OutPoint>()
.map_err(|err| Error::Outpoint {
outpoint: outpoint.into(),
err,
})?,
offset: offset.parse::<u64>().map_err(|err| Error::Offset {
offset: offset.into(),
err,
})?,
})
}
}

#[derive(Debug, Error)]
pub enum Error {
#[error("satpoint `{0}` missing colon")]
Colon(String),
#[error("satpoint offset `{offset}` invalid: {err}")]
Offset { offset: String, err: ParseIntError },
#[error("satpoint outpoint `{outpoint}` invalid: {err}")]
Outpoint {
outpoint: String,
err: ParseOutPointError,
},
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn error() {
assert_eq!(
"foo".parse::<SatPoint>().unwrap_err().to_string(),
"satpoint `foo` missing colon"
);

assert_eq!(
"foo:bar".parse::<SatPoint>().unwrap_err().to_string(),
"satpoint outpoint `foo` invalid: OutPoint not in <txid>:<vout> format"
);

assert_eq!(
"1111111111111111111111111111111111111111111111111111111111111111:1:bar"
.parse::<SatPoint>()
.unwrap_err()
.to_string(),
"satpoint offset `bar` invalid: invalid digit found in string"
);
}

#[test]
fn from_str_ok() {
assert_eq!(
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl<'de> Deserialize<'de> for Decimal {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

Expand Down
17 changes: 0 additions & 17 deletions src/deserialize_from_str.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/inscriptions/inscription_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl<'de> Deserialize<'de> for InscriptionId {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

Expand Down
5 changes: 1 addition & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use {
decimal::Decimal,
decimal_sat::DecimalSat,
degree::Degree,
deserialize_from_str::DeserializeFromStr,
epoch::Epoch,
height::Height,
inscriptions::{media, teleburn, Charm, Media, ParsedEnvelope},
Expand Down Expand Up @@ -53,6 +52,7 @@ use {
derive_more::{Display, FromStr},
html_escaper::{Escape, Trusted},
lazy_static::lazy_static,
ordinals::{DeserializeFromStr, SatPoint},
regex::Regex,
serde::{Deserialize, Deserializer, Serialize, Serializer},
std::{
Expand Down Expand Up @@ -90,7 +90,6 @@ pub use self::{
rarity::Rarity,
runes::{Edict, Rune, RuneId, Runestone},
sat::Sat,
sat_point::SatPoint,
wallet::transaction_builder::{Target, TransactionBuilder},
};

Expand Down Expand Up @@ -118,7 +117,6 @@ mod config;
mod decimal;
mod decimal_sat;
mod degree;
mod deserialize_from_str;
mod epoch;
mod fee_rate;
mod height;
Expand All @@ -131,7 +129,6 @@ pub mod rarity;
mod representation;
pub mod runes;
pub mod sat;
mod sat_point;
mod server_config;
pub mod subcommand;
mod tally;
Expand Down
2 changes: 1 addition & 1 deletion src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<'de> Deserialize<'de> for Object {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/outgoing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl<'de> Deserialize<'de> for Outgoing {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/rarity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<'de> Deserialize<'de> for Rarity {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/runes/rune.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl<'de> Deserialize<'de> for Rune {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/runes/rune_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl<'de> Deserialize<'de> for RuneId {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/runes/spaced_rune.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<'de> Deserialize<'de> for SpacedRune {
where
D: Deserializer<'de>,
{
Ok(DeserializeFromStr::deserialize(deserializer)?.0)
DeserializeFromStr::with(deserializer)
}
}

Expand Down
1 change: 0 additions & 1 deletion src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use {
self::{
accept_encoding::AcceptEncoding,
accept_json::AcceptJson,
deserialize_from_str::DeserializeFromStr,
error::{OptionExt, ServerError, ServerResult},
},
super::*,
Expand Down
3 changes: 2 additions & 1 deletion tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ use {
inscriptions::InscriptionsJson, output::OutputJson, rune::RuneJson, runes::RunesJson,
sat::SatJson, status::StatusJson, transaction::TransactionJson,
},
Edict, InscriptionId, Rune, RuneEntry, RuneId, Runestone, SatPoint,
Edict, InscriptionId, Rune, RuneEntry, RuneId, Runestone,
},
ordinals::SatPoint,
pretty_assertions::assert_eq as pretty_assert_eq,
regex::Regex,
reqwest::{StatusCode, Url},
Expand Down
Loading