staking_cli/
metadata.rs

1use std::{fmt, str::FromStr};
2
3use anyhow::{bail, Result};
4use url::Url;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct MetadataUri(Option<Url>);
8
9impl MetadataUri {
10    pub fn empty() -> Self {
11        Self(None)
12    }
13}
14
15impl TryFrom<Url> for MetadataUri {
16    type Error = anyhow::Error;
17
18    fn try_from(url: Url) -> Result<Self> {
19        if url.as_str().len() > 2048 {
20            bail!("metadata URI cannot exceed 2048 bytes");
21        }
22        Ok(Self(Some(url)))
23    }
24}
25
26impl FromStr for MetadataUri {
27    type Err = anyhow::Error;
28
29    fn from_str(s: &str) -> Result<Self> {
30        let url = Url::parse(s)?;
31        MetadataUri::try_from(url)
32    }
33}
34
35impl fmt::Display for MetadataUri {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match &self.0 {
38            Some(url) => write!(f, "{}", url),
39            None => Ok(()),
40        }
41    }
42}
43
44#[cfg(test)]
45mod test {
46    use super::*;
47
48    #[test]
49    fn test_empty_metadata_uri() {
50        let empty = MetadataUri::empty();
51        assert_eq!(empty.to_string(), "");
52    }
53
54    #[test]
55    fn test_valid_metadata_uri() -> Result<()> {
56        let uri: MetadataUri = "https://example.com/metadata".parse()?;
57        assert_eq!(uri.to_string(), "https://example.com/metadata");
58        Ok(())
59    }
60
61    #[test]
62    fn test_metadata_uri_max_length() -> Result<()> {
63        let long_path = "a".repeat(2000);
64        let url_str = format!("https://example.com/{}", long_path);
65        let uri: MetadataUri = url_str.parse()?;
66        assert_eq!(uri.to_string(), url_str);
67        Ok(())
68    }
69
70    #[test]
71    fn test_metadata_uri_too_long() {
72        let long_path = "a".repeat(2100);
73        let url_str = format!("https://example.com/{}", long_path);
74        let result = url_str.parse::<MetadataUri>();
75        assert!(result.is_err());
76        assert!(result
77            .unwrap_err()
78            .to_string()
79            .contains("cannot exceed 2048 bytes"));
80    }
81}