1use std::ops::{self, Bound};
2
3use crate::api::Result;
4use crate::api::err::Error;
5use crate::core::val;
6use crate::{Object, RecordId, RecordIdKey, Value};
7
8#[derive(Debug)]
15pub struct Table<T>(pub T);
16
17impl<T> Table<T>
18where
19 T: Into<String>,
20{
21 #[allow(dead_code)]
22 pub(crate) fn into_core(self) -> val::Table {
23 unsafe { val::Table::new_unchecked(self.0.into()) }
25 }
26
27 pub fn with_range<R>(self, range: R) -> QueryRange
29 where
30 KeyRange: From<R>,
31 {
32 let range = KeyRange::from(range);
33 let res = val::RecordIdKeyRange {
34 start: range.start.map(RecordIdKey::into_inner),
35 end: range.end.map(RecordIdKey::into_inner),
36 };
37 let res = val::RecordId::new(self.0.into(), Box::new(res));
38 QueryRange(res)
39 }
40}
41
42transparent_wrapper!(
43 #[derive(Clone, PartialEq)]
45 pub struct QueryRange(val::RecordId)
46);
47
48#[derive(Clone, Copy, Eq, PartialEq)]
49pub enum Direction {
50 Out,
51 In,
52 Both,
53}
54
55#[derive(Debug, Clone, PartialEq)]
60#[non_exhaustive]
61pub enum Resource {
62 Table(String),
64 RecordId(RecordId),
66 Object(Object),
68 Array(Vec<Value>),
70 Range(QueryRange),
72 Unspecified,
74}
75
76impl Resource {
77 pub fn with_range(self, range: KeyRange) -> Result<Self> {
79 match self {
80 Resource::Table(table) => Ok(Resource::Range(Table(table).with_range(range))),
81 Resource::RecordId(_) => Err(Error::RangeOnRecordId.into()),
82 Resource::Object(_) => Err(Error::RangeOnObject.into()),
83 Resource::Array(_) => Err(Error::RangeOnArray.into()),
84 Resource::Range(_) => Err(Error::RangeOnRange.into()),
85 Resource::Unspecified => Err(Error::RangeOnUnspecified.into()),
86 }
87 }
88
89 #[cfg(any(feature = "protocol-ws", feature = "protocol-http"))]
90 pub(crate) fn into_core_value(self) -> val::Value {
91 match self {
92 Resource::Table(x) => Table(x).into_core().into(),
93 Resource::RecordId(x) => x.into_inner().into(),
94 Resource::Object(x) => x.into_inner().into(),
95 Resource::Array(x) => Value::array_to_core(x).into(),
96 Resource::Range(x) => x.into_inner().into(),
97 Resource::Unspecified => val::Value::None,
98 }
99 }
100 pub fn is_single_recordid(&self) -> bool {
101 match self {
102 Resource::RecordId(rid) => {
103 !matches!(rid.into_inner_ref().key, val::RecordIdKey::Range(_))
104 }
105 _ => false,
106 }
107 }
108}
109
110impl From<RecordId> for Resource {
111 fn from(thing: RecordId) -> Self {
112 Self::RecordId(thing)
113 }
114}
115
116impl From<&RecordId> for Resource {
117 fn from(thing: &RecordId) -> Self {
118 Self::RecordId(thing.clone())
119 }
120}
121
122impl From<Object> for Resource {
123 fn from(object: Object) -> Self {
124 Self::Object(object)
125 }
126}
127
128impl From<&Object> for Resource {
129 fn from(object: &Object) -> Self {
130 Self::Object(object.clone())
131 }
132}
133
134impl From<Vec<Value>> for Resource {
135 fn from(array: Vec<Value>) -> Self {
136 Self::Array(array)
137 }
138}
139
140impl From<&[Value]> for Resource {
141 fn from(array: &[Value]) -> Self {
142 Self::Array(array.to_vec())
143 }
144}
145
146impl From<&str> for Resource {
147 fn from(s: &str) -> Self {
148 Resource::from(s.to_string())
149 }
150}
151
152impl From<&String> for Resource {
153 fn from(s: &String) -> Self {
154 Self::from(s.as_str())
155 }
156}
157
158impl From<String> for Resource {
159 fn from(s: String) -> Self {
160 Resource::Table(s)
161 }
162}
163
164impl From<QueryRange> for Resource {
165 fn from(value: QueryRange) -> Self {
166 Resource::Range(value)
167 }
168}
169
170impl<T, I> From<(T, I)> for Resource
171where
172 T: Into<String>,
173 I: Into<RecordIdKey>,
174{
175 fn from((table, id): (T, I)) -> Self {
176 let record_id = RecordId::from_table_key(table, id);
177 Self::RecordId(record_id)
178 }
179}
180
181impl From<()> for Resource {
182 fn from(_value: ()) -> Self {
183 Self::Unspecified
184 }
185}
186
187#[derive(Debug, PartialEq, Clone)]
189pub struct KeyRange {
190 pub(crate) start: Bound<RecordIdKey>,
191 pub(crate) end: Bound<RecordIdKey>,
192}
193
194impl<T> From<(Bound<T>, Bound<T>)> for KeyRange
195where
196 T: Into<RecordIdKey>,
197{
198 fn from((start, end): (Bound<T>, Bound<T>)) -> Self {
199 Self {
200 start: match start {
201 Bound::Included(idx) => Bound::Included(idx.into()),
202 Bound::Excluded(idx) => Bound::Excluded(idx.into()),
203 Bound::Unbounded => Bound::Unbounded,
204 },
205 end: match end {
206 Bound::Included(idx) => Bound::Included(idx.into()),
207 Bound::Excluded(idx) => Bound::Excluded(idx.into()),
208 Bound::Unbounded => Bound::Unbounded,
209 },
210 }
211 }
212}
213
214impl<T> From<ops::Range<T>> for KeyRange
215where
216 T: Into<RecordIdKey>,
217{
218 fn from(
219 ops::Range {
220 start,
221 end,
222 }: ops::Range<T>,
223 ) -> Self {
224 Self {
225 start: Bound::Included(start.into()),
226 end: Bound::Excluded(end.into()),
227 }
228 }
229}
230
231impl<T> From<ops::RangeInclusive<T>> for KeyRange
232where
233 T: Into<RecordIdKey>,
234{
235 fn from(range: ops::RangeInclusive<T>) -> Self {
236 let (start, end) = range.into_inner();
237 Self {
238 start: Bound::Included(start.into()),
239 end: Bound::Included(end.into()),
240 }
241 }
242}
243
244impl<T> From<ops::RangeFrom<T>> for KeyRange
245where
246 T: Into<RecordIdKey>,
247{
248 fn from(
249 ops::RangeFrom {
250 start,
251 }: ops::RangeFrom<T>,
252 ) -> Self {
253 Self {
254 start: Bound::Included(start.into()),
255 end: Bound::Unbounded,
256 }
257 }
258}
259
260impl<T> From<ops::RangeTo<T>> for KeyRange
261where
262 T: Into<RecordIdKey>,
263{
264 fn from(
265 ops::RangeTo {
266 end,
267 }: ops::RangeTo<T>,
268 ) -> Self {
269 Self {
270 start: Bound::Unbounded,
271 end: Bound::Excluded(end.into()),
272 }
273 }
274}
275
276impl<T> From<ops::RangeToInclusive<T>> for KeyRange
277where
278 T: Into<RecordIdKey>,
279{
280 fn from(
281 ops::RangeToInclusive {
282 end,
283 }: ops::RangeToInclusive<T>,
284 ) -> Self {
285 Self {
286 start: Bound::Unbounded,
287 end: Bound::Included(end.into()),
288 }
289 }
290}
291
292impl From<ops::RangeFull> for KeyRange {
293 fn from(_: ops::RangeFull) -> Self {
294 Self {
295 start: Bound::Unbounded,
296 end: Bound::Unbounded,
297 }
298 }
299}
300
301pub trait IntoResource<Output>: into_resource::Sealed<Output> {}
303
304mod into_resource {
305 pub trait Sealed<Output> {
306 fn into_resource(self) -> super::Result<super::Resource>;
307 }
308}
309
310pub trait CreateResource<Output>: create_resource::Sealed<Output> {}
313
314mod create_resource {
315 pub trait Sealed<Output> {
316 fn into_resource(self) -> super::Result<super::Resource>;
317 }
318}
319
320fn no_colon(a: &str) -> Result<()> {
321 if a.contains(':') {
322 return Err(Error::TableColonId {
323 table: a.to_string(),
324 }
325 .into());
326 }
327 Ok(())
328}
329
330impl IntoResource<Value> for Resource {}
333impl into_resource::Sealed<Value> for Resource {
334 fn into_resource(self) -> Result<Resource> {
335 Ok(self)
336 }
337}
338
339impl<R> IntoResource<Option<R>> for Object {}
340impl<R> into_resource::Sealed<Option<R>> for Object {
341 fn into_resource(self) -> Result<Resource> {
342 Ok(self.into())
343 }
344}
345
346impl<R> IntoResource<Option<R>> for RecordId {}
347impl<R> into_resource::Sealed<Option<R>> for RecordId {
348 fn into_resource(self) -> Result<Resource> {
349 Ok(self.into())
350 }
351}
352
353impl<R> IntoResource<Option<R>> for &RecordId {}
354impl<R> into_resource::Sealed<Option<R>> for &RecordId {
355 fn into_resource(self) -> Result<Resource> {
356 Ok(self.clone().into())
357 }
358}
359
360impl<R, T, I> IntoResource<Option<R>> for (T, I)
361where
362 T: Into<String>,
363 I: Into<RecordIdKey>,
364{
365}
366impl<R, T, I> into_resource::Sealed<Option<R>> for (T, I)
367where
368 T: Into<String>,
369 I: Into<RecordIdKey>,
370{
371 fn into_resource(self) -> Result<Resource> {
372 Ok(self.into())
373 }
374}
375
376impl<R> IntoResource<Vec<R>> for Vec<Value> {}
377impl<R> into_resource::Sealed<Vec<R>> for Vec<Value> {
378 fn into_resource(self) -> Result<Resource> {
379 Ok(self.into())
380 }
381}
382
383impl<R> IntoResource<Vec<R>> for QueryRange {}
384impl<R> into_resource::Sealed<Vec<R>> for QueryRange {
385 fn into_resource(self) -> Result<Resource> {
386 Ok(self.into())
387 }
388}
389
390impl<T, R> IntoResource<Vec<R>> for Table<T> where T: Into<String> {}
391impl<T, R> into_resource::Sealed<Vec<R>> for Table<T>
392where
393 T: Into<String>,
394{
395 fn into_resource(self) -> Result<Resource> {
396 let t = self.0.into();
397 Ok(t.into())
398 }
399}
400
401impl<R> IntoResource<Vec<R>> for &str {}
402impl<R> into_resource::Sealed<Vec<R>> for &str {
403 fn into_resource(self) -> Result<Resource> {
404 no_colon(self)?;
405 Ok(self.into())
406 }
407}
408
409impl<R> IntoResource<Vec<R>> for String {}
410impl<R> into_resource::Sealed<Vec<R>> for String {
411 fn into_resource(self) -> Result<Resource> {
412 no_colon(&self)?;
413 Ok(self.into())
414 }
415}
416
417impl<R> IntoResource<Vec<R>> for &String {}
418impl<R> into_resource::Sealed<Vec<R>> for &String {
419 fn into_resource(self) -> Result<Resource> {
420 no_colon(self)?;
421 Ok(self.into())
422 }
423}
424
425impl<R> IntoResource<Vec<R>> for () {}
426impl<R> into_resource::Sealed<Vec<R>> for () {
427 fn into_resource(self) -> Result<Resource> {
428 Ok(Resource::Unspecified)
429 }
430}
431
432impl CreateResource<Value> for Resource {}
435impl create_resource::Sealed<Value> for Resource {
436 fn into_resource(self) -> Result<Resource> {
437 Ok(self)
438 }
439}
440
441impl<R> CreateResource<Option<R>> for Object {}
442impl<R> create_resource::Sealed<Option<R>> for Object {
443 fn into_resource(self) -> Result<Resource> {
444 Ok(self.into())
445 }
446}
447
448impl<R> CreateResource<Option<R>> for RecordId {}
449impl<R> create_resource::Sealed<Option<R>> for RecordId {
450 fn into_resource(self) -> Result<Resource> {
451 Ok(self.into())
452 }
453}
454
455impl<R> CreateResource<Option<R>> for &RecordId {}
456impl<R> create_resource::Sealed<Option<R>> for &RecordId {
457 fn into_resource(self) -> Result<Resource> {
458 Ok(self.clone().into())
459 }
460}
461
462impl<R, T, I> CreateResource<Option<R>> for (T, I)
463where
464 T: Into<String>,
465 I: Into<RecordIdKey>,
466{
467}
468impl<R, T, I> create_resource::Sealed<Option<R>> for (T, I)
469where
470 T: Into<String>,
471 I: Into<RecordIdKey>,
472{
473 fn into_resource(self) -> Result<Resource> {
474 Ok(self.into())
475 }
476}
477
478impl<T, R> CreateResource<Option<R>> for Table<T> where T: Into<String> {}
479impl<T, R> create_resource::Sealed<Option<R>> for Table<T>
480where
481 T: Into<String>,
482{
483 fn into_resource(self) -> Result<Resource> {
484 let t = self.0.into();
485 Ok(t.into())
486 }
487}
488
489impl<R> CreateResource<Option<R>> for &str {}
490impl<R> create_resource::Sealed<Option<R>> for &str {
491 fn into_resource(self) -> Result<Resource> {
492 no_colon(self)?;
493 Ok(self.into())
494 }
495}
496
497impl<R> CreateResource<Option<R>> for String {}
498impl<R> create_resource::Sealed<Option<R>> for String {
499 fn into_resource(self) -> Result<Resource> {
500 no_colon(&self)?;
501 Ok(self.into())
502 }
503}
504
505impl<R> CreateResource<Option<R>> for &String {}
506impl<R> create_resource::Sealed<Option<R>> for &String {
507 fn into_resource(self) -> Result<Resource> {
508 no_colon(self)?;
509 Ok(self.into())
510 }
511}