1use std::borrow::Cow;
2
3use nimiq_database_value::{AsDatabaseBytes, FromDatabaseBytes};
4
5use crate::traits::{DupTableValue, Key, Value};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct IndexedValue<I: Key, V: Value> {
14 pub index: I,
16 pub value: V,
18}
19
20impl<I: Key, V: Value> IndexedValue<I, V> {
21 pub fn new(index: I, value: V) -> Self {
23 Self { index, value }
24 }
25}
26
27impl<I: Key, V: Value> DupTableValue for IndexedValue<I, V> {
28 type SubKey = I;
30
31 type Value = V;
33
34 fn subkey(&self) -> &Self::SubKey {
36 &self.index
37 }
38
39 fn value(&self) -> &Self::Value {
41 &self.value
42 }
43}
44
45impl<I: Key, V: Value> AsDatabaseBytes for IndexedValue<I, V> {
46 fn as_key_bytes(&self) -> Cow<'_, [u8]> {
47 let bytes = [
48 &self.index.as_value_bytes()[..],
49 &self.value.as_value_bytes()[..],
50 ]
51 .concat();
52 Cow::Owned(bytes)
53 }
54
55 const FIXED_SIZE: Option<usize> = match (I::FIXED_SIZE, V::FIXED_SIZE) {
56 (Some(index_len), Some(value_len)) => Some(index_len + value_len),
57 (Some(_), None) => None,
58 (None, _) => panic!("Index must have a fixed size"),
59 };
60}
61
62impl<I: Key, V: Value> FromDatabaseBytes for IndexedValue<I, V> {
63 fn from_key_bytes(bytes: &[u8]) -> Self
64 where
65 Self: Sized,
66 {
67 let index_size = I::FIXED_SIZE.expect("Index must have a fixed size");
68 IndexedValue {
69 index: I::from_value_bytes(&bytes[..index_size]),
70 value: V::from_value_bytes(&bytes[index_size..]),
71 }
72 }
73}