templar_common/oracle/redstone/
feed_id.rs1use std::{fmt::Display, ops::Deref, sync::Arc};
2
3use near_sdk::near;
4
5#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
6#[near(serializers = [json, borsh])]
7pub struct FeedId(Arc<str>);
8
9impl Deref for FeedId {
10 type Target = str;
11
12 fn deref(&self) -> &Self::Target {
13 &self.0
14 }
15}
16
17impl Clone for FeedId {
18 fn clone(&self) -> Self {
19 Self(Arc::clone(&self.0))
20 }
21}
22
23impl AsRef<str> for FeedId {
24 fn as_ref(&self) -> &str {
25 &self.0
26 }
27}
28
29impl From<&str> for FeedId {
30 fn from(value: &str) -> Self {
31 Self(Arc::from(value))
32 }
33}
34
35impl From<String> for FeedId {
36 fn from(value: String) -> Self {
37 Self(Arc::from(value))
38 }
39}
40
41impl Display for FeedId {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 self.0.fmt(f)
44 }
45}
46
47impl From<redstone::FeedId> for FeedId {
48 fn from(id: redstone::FeedId) -> Self {
49 let bytes = id.to_array();
50
51 let mut end = bytes.len();
52 while end > 0 && bytes[end - 1] == 0 {
53 end -= 1;
54 }
55
56 Self(Arc::from(String::from_utf8_lossy(&bytes[..end])))
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 #[test]
66 fn test_feed_to_string_simple() {
67 let btc_feed_id_array: [u8; 32] = [
68 66, 84, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0,
70 ];
71
72 let btc_feed_id = redstone::FeedId::from(btc_feed_id_array);
73
74 let convert_btc_feed_id_to_string = super::FeedId::from(btc_feed_id);
75
76 assert_eq!(convert_btc_feed_id_to_string, "BTC".into());
77
78 let non_btc_feed_id_array: [u8; 32] = [
79 66, 84, 67, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0,
81 ];
82
83 let non_btc_feed_id = redstone::FeedId::from(non_btc_feed_id_array);
84
85 let convert_non_btc_feed_id_to_string = super::FeedId::from(non_btc_feed_id);
86
87 assert_eq!(convert_non_btc_feed_id_to_string, "BTC\0C".into());
88 }
89
90 #[test]
91 fn test_feed_to_string_all_zero_bytes() {
92 let feed_id = redstone::FeedId::from([0u8; 32]);
93 let converted = super::FeedId::from(feed_id);
94 assert_eq!(converted, "".into());
95 }
96
97 #[test]
98 fn test_feed_to_string_invalid_utf8_is_lossy() {
99 let mut bytes = [0u8; 32];
100 bytes[0] = 0xFF;
101 bytes[1] = b'B';
102 let feed_id = redstone::FeedId::from(bytes);
103 let converted = super::FeedId::from(feed_id);
104 assert_eq!(converted.as_ref(), "�B");
105 }
106}