nimiq_database_value/
lib.rs1use std::{borrow::Cow, ffi::CStr, mem, slice};
2
3pub trait IntoDatabaseValue {
4 fn database_byte_size(&self) -> usize;
5 fn copy_into_database(&self, bytes: &mut [u8]);
6}
7
8pub trait FromDatabaseBytes {
9 fn from_key_bytes(bytes: &[u8]) -> Self
12 where
13 Self: Sized;
14
15 fn from_value_bytes(bytes: &[u8]) -> Self
19 where
20 Self: Sized,
21 {
22 Self::from_key_bytes(bytes)
23 }
24}
25
26pub trait AsDatabaseBytes {
27 fn as_key_bytes(&self) -> Cow<'_, [u8]>;
30
31 fn as_value_bytes(&self) -> Cow<'_, [u8]> {
35 self.as_key_bytes()
36 }
37
38 const FIXED_SIZE: Option<usize> = None;
41}
42
43impl AsDatabaseBytes for () {
44 fn as_key_bytes(&self) -> Cow<'_, [u8]> {
45 Cow::Borrowed(&[])
46 }
47
48 const FIXED_SIZE: Option<usize> = Some(0);
49}
50
51impl FromDatabaseBytes for () {
52 fn from_key_bytes(bytes: &[u8]) -> Self
53 where
54 Self: Sized,
55 {
56 assert!(bytes.is_empty());
57 }
58}
59
60impl IntoDatabaseValue for [u8] {
62 fn database_byte_size(&self) -> usize {
63 self.len()
64 }
65
66 fn copy_into_database(&self, bytes: &mut [u8]) {
67 bytes.copy_from_slice(self);
68 }
69}
70
71impl IntoDatabaseValue for str {
72 fn database_byte_size(&self) -> usize {
73 self.len()
74 }
75
76 fn copy_into_database(&self, bytes: &mut [u8]) {
77 bytes.copy_from_slice(self.as_bytes());
78 }
79}
80
81impl FromDatabaseBytes for String {
82 fn from_key_bytes(bytes: &[u8]) -> Self
83 where
84 Self: Sized,
85 {
86 String::from_utf8(bytes.to_vec()).unwrap()
87 }
88}
89
90impl FromDatabaseBytes for Vec<u8> {
91 fn from_key_bytes(bytes: &[u8]) -> Self
92 where
93 Self: Sized,
94 {
95 bytes.to_vec()
96 }
97}
98
99impl AsDatabaseBytes for Vec<u8> {
100 fn as_key_bytes(&self) -> Cow<'_, [u8]> {
101 Cow::Borrowed(&self[..])
102 }
103}
104
105impl AsDatabaseBytes for String {
106 fn as_key_bytes(&self) -> Cow<'_, [u8]> {
107 Cow::Borrowed(self.as_bytes())
108 }
109}
110
111impl AsDatabaseBytes for str {
112 fn as_key_bytes(&self) -> Cow<'_, [u8]> {
113 Cow::Borrowed(self.as_bytes())
114 }
115}
116
117impl AsDatabaseBytes for CStr {
118 fn as_key_bytes(&self) -> Cow<'_, [u8]> {
119 Cow::Borrowed(self.to_bytes())
120 }
121}
122
123macro_rules! impl_num_traits {
124 ($typ:ident) => {
125 impl FromDatabaseBytes for $typ {
126 fn from_key_bytes(bytes: &[u8]) -> Self
127 where
128 Self: Sized,
129 {
130 $typ::from_ne_bytes(bytes.try_into().expect("mismatch size"))
131 }
132
133 fn from_value_bytes(bytes: &[u8]) -> Self
134 where
135 Self: Sized,
136 {
137 $typ::from_be_bytes(bytes.try_into().expect("mismatch size"))
139 }
140 }
141 impl AsDatabaseBytes for $typ {
142 fn as_key_bytes(&self) -> Cow<'_, [u8]> {
143 unsafe {
144 #[allow(clippy::size_of_in_element_count)]
145 Cow::Borrowed(slice::from_raw_parts(
146 self as *const $typ as *const u8,
147 mem::size_of::<$typ>(),
148 ))
149 }
150 }
151
152 fn as_value_bytes(&self) -> Cow<'_, [u8]> {
153 Cow::Owned(self.to_be_bytes().to_vec())
155 }
156
157 const FIXED_SIZE: Option<usize> = Some($typ::BITS as usize / 8);
158 }
159 };
160}
161
162impl_num_traits!(u16);
163impl_num_traits!(u32);
164impl_num_traits!(u64);