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