1use std::{borrow::Cow, collections::BTreeMap};
2
3use crate::{
4 Array, ByteString, DateTime, EpochTime, Float, Map, SimpleValue, TextString, Value,
5 codec::{Head, Major},
6 view::{Payload, ValueView},
7};
8
9#[derive(Debug)]
55pub struct ValueKey<'a>(Inner<'a>);
56
57#[derive(Debug)]
58enum Inner<'a> {
59 Array(&'a [Value<'a>]),
60 Map(&'a BTreeMap<Value<'a>, Value<'a>>),
61 Other(Cow<'a, Value<'a>>),
62}
63
64impl ValueKey<'_> {
65 pub(crate) fn to_usize(&self) -> Option<usize> {
66 if let Inner::Other(value) = &self.0 {
67 value.to_usize().ok()
68 } else {
69 None
70 }
71 }
72}
73
74impl<'a> From<Value<'a>> for ValueKey<'a> {
75 fn from(value: Value<'a>) -> Self {
76 Self(Inner::Other(Cow::Owned(value)))
77 }
78}
79
80impl<'a> From<&'a Value<'a>> for ValueKey<'a> {
81 fn from(value: &'a Value<'a>) -> Self {
82 Self(Inner::Other(Cow::Borrowed(value)))
83 }
84}
85
86impl<'a> From<&'a [Value<'a>]> for ValueKey<'a> {
87 fn from(value: &'a [Value<'a>]) -> Self {
88 Self(Inner::Array(value))
89 }
90}
91
92impl<'a> From<&'a Array<'a>> for ValueKey<'a> {
93 fn from(value: &'a Array<'a>) -> Self {
94 Self(Inner::Array(&value.0))
95 }
96}
97
98impl<'a> From<&'a Map<'a>> for ValueKey<'a> {
99 fn from(value: &'a Map<'a>) -> Self {
100 Self(Inner::Map(&value.0))
101 }
102}
103
104impl<'a> From<&'a BTreeMap<Value<'a>, Value<'a>>> for ValueKey<'a> {
105 fn from(value: &'a BTreeMap<Value<'a>, Value<'a>>) -> Self {
106 Self(Inner::Map(value))
107 }
108}
109
110impl<'a, T> From<&'a Vec<T>> for ValueKey<'a>
111where
112 ValueKey<'a>: From<&'a [T]>,
113{
114 fn from(value: &'a Vec<T>) -> Self {
115 value.as_slice().into()
116 }
117}
118
119impl<'a, T, const N: usize> From<&'a [T; N]> for ValueKey<'a>
120where
121 ValueKey<'a>: From<&'a [T]>,
122{
123 fn from(value: &'a [T; N]) -> Self {
124 value.as_slice().into()
125 }
126}
127
128impl<'a, const N: usize> From<[u8; N]> for ValueKey<'a> {
129 fn from(value: [u8; N]) -> Self {
130 Self(Inner::Other(Cow::Owned(Value::from(value))))
131 }
132}
133
134impl<'a, const N: usize> From<[Value<'a>; N]> for ValueKey<'a> {
135 fn from(value: [Value<'a>; N]) -> Self {
136 Self(Inner::Other(Cow::Owned(Value::from(value))))
137 }
138}
139
140macro_rules! impl_from {
147 ($($type:ty),* $(,)?) => { $(
148 impl<'a> From<$type> for ValueKey<'a> {
149 fn from(value: $type) -> Self {
150 Self(Inner::Other(Cow::Owned(Value::from(value))))
151 }
152 }
153 )* }
154}
155
156impl_from!(bool, SimpleValue, (), char);
157impl_from!(u8, u16, u32, u64, u128, usize);
158impl_from!(i8, i16, i32, i64, i128, isize);
159impl_from!(f32, f64, Float);
160impl_from!(DateTime, &'a DateTime, EpochTime);
161impl_from!(TextString<'a>, &'a TextString<'a>, ByteString<'a>, &'a ByteString<'a>);
162impl_from!(&'a str, &'a String, String, Box<str>, Cow<'a, str>);
163impl_from!(&'a [u8], Vec<u8>, Box<[u8]>, Cow<'a, [u8]>);
164impl_from!(Array<'a>, Map<'a>);
165impl_from!(Vec<Value<'a>>, Box<[Value<'a>]>, BTreeMap<Value<'a>, Value<'a>>);
166
167impl ValueView for ValueKey<'_> {
168 fn head(&self) -> Head {
169 match &self.0 {
170 Inner::Array(arr) => Head::from_usize(Major::Array, arr.len()),
171 Inner::Map(map) => Head::from_usize(Major::Map, map.len()),
172 Inner::Other(value) => value.head(),
173 }
174 }
175
176 fn payload(&self) -> Payload<'_> {
177 match &self.0 {
178 Inner::Array(arr) => Payload::Array(arr),
179 Inner::Map(map) => Payload::Map(map),
180 Inner::Other(value) => value.payload(),
181 }
182 }
183}