Skip to content

Commit

Permalink
Move SatPoint into library (ordinals#3077)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Feb 2, 2024
1 parent cf48655 commit b6de2d4
Show file tree
Hide file tree
Showing 23 changed files with 166 additions and 41 deletions.
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.
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

0 comments on commit b6de2d4

Please sign in to comment.