mod bytes;
mod equal;
mod from_bits;
mod from_field;
mod parse;
mod serialize;
mod size_in_bits;
mod to_bits;
mod to_field;
use snarkvm_console_network::Network;
use snarkvm_console_types::{Field, prelude::*};
#[derive(Copy, Clone)]
pub struct Identifier<N: Network>(Field<N>, u8);
impl<N: Network> From<&Identifier<N>> for Identifier<N> {
fn from(identifier: &Identifier<N>) -> Self {
*identifier
}
}
impl<N: Network> TryFrom<String> for Identifier<N> {
type Error = Error;
fn try_from(identifier: String) -> Result<Self> {
Self::from_str(&identifier)
}
}
impl<N: Network> TryFrom<&String> for Identifier<N> {
type Error = Error;
fn try_from(identifier: &String) -> Result<Self> {
Self::from_str(identifier)
}
}
impl<N: Network> TryFrom<&str> for Identifier<N> {
type Error = Error;
fn try_from(identifier: &str) -> Result<Self> {
Self::from_str(identifier)
}
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use snarkvm_console_network::MainnetV0;
type CurrentNetwork = MainnetV0;
const ITERATIONS: usize = 100;
pub(crate) fn sample_identifier<N: Network>(rng: &mut TestRng) -> Result<Identifier<N>> {
let string = sample_identifier_as_string::<N>(rng)?;
let field = Field::<N>::from_bits_le(&string.as_bytes().to_bits_le())?;
Ok(Identifier(field, u8::try_from(string.len()).or_halt_with::<CurrentNetwork>("Invalid identifier length")))
}
pub(crate) fn sample_identifier_as_string<N: Network>(rng: &mut TestRng) -> Result<String> {
let string = "a".to_string()
+ &rng
.sample_iter(&Alphanumeric)
.take(Field::<N>::size_in_data_bits() / (8 * 2))
.map(char::from)
.collect::<String>();
let max_bytes = Field::<N>::size_in_data_bits() / 8; match string.len() <= max_bytes {
true => Ok(string),
false => bail!("Identifier exceeds the maximum capacity allowed"),
}
}
pub(crate) fn sample_lowercase_identifier_as_string<N: Network>(rng: &mut TestRng) -> Result<String> {
let string = sample_identifier_as_string::<N>(rng)?;
Ok(string.to_lowercase())
}
#[test]
fn test_try_from() -> Result<()> {
let mut rng = TestRng::default();
for _ in 0..ITERATIONS {
let expected_string = sample_identifier_as_string::<CurrentNetwork>(&mut rng)?;
let expected_field = Field::<CurrentNetwork>::from_bits_le(&expected_string.as_bytes().to_bits_le())?;
let candidate = Identifier::<CurrentNetwork>::try_from(expected_string.as_str())?;
assert_eq!(expected_field, candidate.0);
assert_eq!(expected_string.len(), candidate.1 as usize);
}
Ok(())
}
#[test]
fn test_identifier_try_from_illegal() {
assert!(Identifier::<CurrentNetwork>::try_from("123").is_err());
assert!(Identifier::<CurrentNetwork>::try_from("abc\x08def").is_err());
assert!(Identifier::<CurrentNetwork>::try_from("abc\u{202a}def").is_err());
}
}