made_core/value_objects/
output_contract_id.rs1use std::borrow::Borrow;
2use std::fmt;
3
4use serde::{Deserialize, Serialize};
5
6use crate::error::DomainError;
7
8const MAX_OUTPUT_CONTRACT_ID_LEN: usize = 128;
9
10#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
12#[serde(transparent)]
13pub struct OutputContractId(String);
14
15impl OutputContractId {
16 pub fn new(raw: impl Into<String>) -> Result<Self, DomainError> {
17 let raw = raw.into();
18 let value = raw.trim();
19 if value.is_empty() {
20 return Err(DomainError::EmptyField {
21 field: "output_contract.contract_id",
22 });
23 }
24 if value.len() > MAX_OUTPUT_CONTRACT_ID_LEN {
25 return Err(DomainError::FieldTooLong {
26 field: "output_contract.contract_id",
27 actual: value.len(),
28 max: MAX_OUTPUT_CONTRACT_ID_LEN,
29 });
30 }
31 Ok(Self(value.to_owned()))
32 }
33
34 #[must_use]
35 pub fn as_str(&self) -> &str {
36 &self.0
37 }
38}
39
40impl Borrow<str> for OutputContractId {
41 fn borrow(&self) -> &str {
42 self.as_str()
43 }
44}
45
46impl fmt::Display for OutputContractId {
47 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
48 formatter.write_str(self.as_str())
49 }
50}
51
52impl PartialEq<str> for OutputContractId {
53 fn eq(&self, other: &str) -> bool {
54 self.as_str() == other
55 }
56}
57
58impl PartialEq<&str> for OutputContractId {
59 fn eq(&self, other: &&str) -> bool {
60 self.as_str() == *other
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn trims_a_valid_identity() {
70 assert_eq!(OutputContractId::new(" report-v1 ").unwrap(), "report-v1");
71 }
72
73 #[test]
74 fn rejects_an_empty_identity() {
75 assert!(OutputContractId::new(" ").is_err());
76 }
77}