Skip to content

Commit

Permalink
Merge pull request #421 from dusk-network/neotamandua/from_string
Browse files Browse the repository at this point in the history
uplink: impl TryFrom<String> for ContractId
  • Loading branch information
Neotamandua authored Feb 20, 2025
2 parents 38694d4 + 79e9d51 commit c7015f5
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
5 changes: 5 additions & 0 deletions piecrust-uplink/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add `TryFrom<String>` trait impl for `ContractId` [#420]

## [0.17.3] - 2024-12-19

## [0.17.2] - 2024-12-17
Expand Down Expand Up @@ -226,6 +230,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- First `piecrust-uplink` release

<!-- ISSUES -->
[#420]: https://github.com/dusk-network/piecrust/issues/420
[#414]: https://github.com/dusk-network/piecrust/issues/414
[#375]: https://github.com/dusk-network/piecrust/issues/375
[#365]: https://github.com/dusk-network/piecrust/issues/365
Expand Down
4 changes: 2 additions & 2 deletions piecrust-uplink/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ rkyv = { version = "0.7", default-features = false, features = ["size_32", "allo
bytecheck = { version = "0.6", default-features = false }
dlmalloc = { version = "0.2", optional = true, features = ["global"] }
serde = { version = "1.0", optional = true }
hex = { version = "0.4" , optional = true }
hex = { version = "0.4", default-features = false, features = ["alloc"]}
base64 = { version = "0.22", optional = true }
serde_json = { version = "1.0", optional = true }

Expand All @@ -27,7 +27,7 @@ rand = "0.8"
[features]
abi = []
debug = []
serde = ["dep:serde", "serde_json", "hex", "base64"]
serde = ["dep:serde", "serde_json", "base64"]

[package.metadata.docs.rs]
all-features = true
Expand Down
80 changes: 80 additions & 0 deletions piecrust-uplink/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,20 @@ impl PartialEq<[u8; CONTRACT_ID_BYTES]> for ContractId {
}
}

/// Debug implementation for [`ContractId`]
///
/// This implementation uses the normal display implementation.
impl core::fmt::Debug for ContractId {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::fmt::Display::fmt(self, f)
}
}

/// Display implementation for [`ContractId`]
///
/// This implementation will display the hexadecimal representation of the bytes
/// of the [`ContractId`]. If the alternate flag is set, it will also display
/// the `0x` prefix.
impl core::fmt::Display for ContractId {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
if f.alternate() {
Expand All @@ -127,3 +135,75 @@ impl core::fmt::Display for ContractId {
Ok(())
}
}

impl TryFrom<String> for ContractId {
type Error = core::fmt::Error;

/// Tries to convert a hexadecimal string into a [`ContractId`]
///
/// The string can be prefixed with `0x` or not.
fn try_from(value: String) -> core::result::Result<Self, Self::Error> {
let value = value.trim_start_matches("0x");
let decoded = hex::decode(value).map_err(|_| core::fmt::Error)?;
let bytes: [u8; CONTRACT_ID_BYTES] =
decoded.try_into().map_err(|_| core::fmt::Error)?;

Ok(ContractId::from_bytes(bytes))
}
}

#[cfg(test)]
mod tests {
use alloc::{format, string::ToString};

use rand::rngs::StdRng;
use rand::{Rng, SeedableRng};

use super::*;

const CONTRACT_ID_STR: &str =
"0000000000000000000000000000000000000000000000000000000000000000";
const CONTRACT_ID_STR_PRETTY: &str =
"0x0000000000000000000000000000000000000000000000000000000000000000";

#[test]
fn contract_id_display() {
let contract_id = ContractId::from_bytes([0u8; CONTRACT_ID_BYTES]);
assert_eq!(format!("{}", contract_id), CONTRACT_ID_STR);

let contract_id = ContractId::from_bytes([0u8; CONTRACT_ID_BYTES]);
assert_eq!(format!("{:#?}", contract_id), CONTRACT_ID_STR_PRETTY);
}

#[test]
fn contract_id_debug() {
let contract_id = ContractId::from_bytes([0u8; CONTRACT_ID_BYTES]);
assert_eq!(format!("{}", contract_id), CONTRACT_ID_STR);
}

#[test]
fn contract_id_to_from_string() {
let mut rng = StdRng::seed_from_u64(1618);
let contract_id = ContractId::from_bytes(rng.gen());

let string = contract_id.to_string();

assert_eq!(string.starts_with("0x"), false);
assert_eq!(string.len(), CONTRACT_ID_BYTES * 2);

let contract_id_from_string = ContractId::try_from(string).unwrap();

assert_eq!(contract_id, contract_id_from_string);
}

#[test]
fn contract_id_try_from_invalid_string() {
let too_short = ContractId::try_from("0x".to_string()).is_err();

let too_long =
ContractId::try_from(format!("{}0", CONTRACT_ID_STR)).is_err();

assert!(too_short);
assert!(too_long);
}
}

0 comments on commit c7015f5

Please sign in to comment.