1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
use core::fmt::{Debug, Display, Error as FmtError, Formatter};
use core::str::FromStr;
use derive_more::Into;
use ibc_primitives::prelude::*;
use crate::error::IdentifierError;
use crate::validate::validate_channel_identifier;
const CHANNEL_ID_PREFIX: &str = "channel";
#[cfg_attr(
feature = "parity-scale-codec",
derive(
parity_scale_codec::Encode,
parity_scale_codec::Decode,
scale_info::TypeInfo
)
)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Into)]
pub struct ChannelId(String);
impl ChannelId {
/// Builds a new channel identifier. Like client and connection identifiers, channel ids are
/// deterministically formed from two elements: a prefix `prefix`, and a monotonically
/// increasing `counter`, separated by a dash "-".
/// The prefix is currently determined statically (see `ChannelId::prefix()`) so this method
/// accepts a single argument, the `counter`.
///
/// ```
/// # use ibc_core_host_types::identifiers::ChannelId;
/// let chan_id = ChannelId::new(27);
/// assert_eq!(chan_id.to_string(), "channel-27");
/// ```
pub fn new(identifier: u64) -> Self {
let id = format!("{}-{}", Self::prefix(), identifier);
Self(id)
}
/// Returns the static prefix to be used across all channel identifiers.
pub fn prefix() -> &'static str {
CHANNEL_ID_PREFIX
}
/// Get this identifier as a borrowed `&str`
pub fn as_str(&self) -> &str {
&self.0
}
/// Get this identifier as a borrowed byte slice
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn zero() -> Self {
Self::new(0)
}
}
/// This implementation provides a `to_string` method.
impl Display for ChannelId {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
write!(f, "{}", self.0)
}
}
impl FromStr for ChannelId {
type Err = IdentifierError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
validate_channel_identifier(s).map(|_| Self(s.to_string()))
}
}
impl AsRef<str> for ChannelId {
fn as_ref(&self) -> &str {
&self.0
}
}
/// Equality check against string literal (satisfies &ChannelId == &str).
/// ```
/// use core::str::FromStr;
/// use ibc_core_host_types::identifiers::ChannelId;
/// let channel_id = ChannelId::from_str("channel-0");
/// assert!(channel_id.is_ok());
/// channel_id.map(|id| {assert_eq!(&id, "channel-0")});
/// ```
impl PartialEq<str> for ChannelId {
fn eq(&self, other: &str) -> bool {
self.as_str().eq(other)
}
}