1use crate::cnf::ID_CHARS;
2use crate::ctx::Context;
3use crate::dbs::{Options, Transaction};
4use crate::doc::CursorDoc;
5use crate::err::Error;
6use crate::sql::{escape::escape_rid, Array, Number, Object, Strand, Thing, Uuid, Value};
7use nanoid::nanoid;
8use revision::revisioned;
9use serde::{Deserialize, Serialize};
10use std::fmt::{self, Display, Formatter};
11use ulid::Ulid;
12
13#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
14#[revisioned(revision = 1)]
15pub enum Gen {
16 Rand,
17 Ulid,
18 Uuid,
19}
20
21#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
22#[revisioned(revision = 1)]
23pub enum Id {
24 Number(i64),
25 String(String),
26 Array(Array),
27 Object(Object),
28 Generate(Gen),
29}
30
31impl From<i64> for Id {
32 fn from(v: i64) -> Self {
33 Self::Number(v)
34 }
35}
36
37impl From<i32> for Id {
38 fn from(v: i32) -> Self {
39 Self::Number(v as i64)
40 }
41}
42
43impl From<u64> for Id {
44 fn from(v: u64) -> Self {
45 Self::Number(v as i64)
46 }
47}
48
49impl From<String> for Id {
50 fn from(v: String) -> Self {
51 Self::String(v)
52 }
53}
54
55impl From<Array> for Id {
56 fn from(v: Array) -> Self {
57 Self::Array(v)
58 }
59}
60
61impl From<Object> for Id {
62 fn from(v: Object) -> Self {
63 Self::Object(v)
64 }
65}
66
67impl From<Uuid> for Id {
68 fn from(v: Uuid) -> Self {
69 Self::String(v.to_raw())
70 }
71}
72
73impl From<Strand> for Id {
74 fn from(v: Strand) -> Self {
75 Self::String(v.as_string())
76 }
77}
78
79impl From<&str> for Id {
80 fn from(v: &str) -> Self {
81 Self::String(v.to_owned())
82 }
83}
84
85impl From<&String> for Id {
86 fn from(v: &String) -> Self {
87 Self::String(v.to_owned())
88 }
89}
90
91impl From<Vec<&str>> for Id {
92 fn from(v: Vec<&str>) -> Self {
93 Id::Array(v.into())
94 }
95}
96
97impl From<Vec<String>> for Id {
98 fn from(v: Vec<String>) -> Self {
99 Id::Array(v.into())
100 }
101}
102
103impl From<Vec<Value>> for Id {
104 fn from(v: Vec<Value>) -> Self {
105 Id::Array(v.into())
106 }
107}
108
109impl From<Number> for Id {
110 fn from(v: Number) -> Self {
111 match v {
112 Number::Int(v) => v.into(),
113 Number::Float(v) => v.to_string().into(),
114 Number::Decimal(v) => v.to_string().into(),
115 }
116 }
117}
118
119impl From<Thing> for Id {
120 fn from(v: Thing) -> Self {
121 v.id
122 }
123}
124
125impl Id {
126 pub fn rand() -> Self {
128 Self::String(nanoid!(20, &ID_CHARS))
129 }
130 pub fn ulid() -> Self {
132 Self::String(Ulid::new().to_string())
133 }
134 pub fn uuid() -> Self {
136 Self::String(Uuid::new_v7().to_raw())
137 }
138 pub fn to_raw(&self) -> String {
140 match self {
141 Self::Number(v) => v.to_string(),
142 Self::String(v) => v.to_string(),
143 Self::Array(v) => v.to_string(),
144 Self::Object(v) => v.to_string(),
145 Self::Generate(v) => match v {
146 Gen::Rand => "rand()".to_string(),
147 Gen::Ulid => "ulid()".to_string(),
148 Gen::Uuid => "uuid()".to_string(),
149 },
150 }
151 }
152}
153
154impl Display for Id {
155 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
156 match self {
157 Self::Number(v) => Display::fmt(v, f),
158 Self::String(v) => Display::fmt(&escape_rid(v), f),
159 Self::Array(v) => Display::fmt(v, f),
160 Self::Object(v) => Display::fmt(v, f),
161 Self::Generate(v) => match v {
162 Gen::Rand => Display::fmt("rand()", f),
163 Gen::Ulid => Display::fmt("ulid()", f),
164 Gen::Uuid => Display::fmt("uuid()", f),
165 },
166 }
167 }
168}
169
170impl Id {
171 pub(crate) async fn compute(
173 &self,
174 ctx: &Context<'_>,
175 opt: &Options,
176 txn: &Transaction,
177 doc: Option<&CursorDoc<'_>>,
178 ) -> Result<Id, Error> {
179 match self {
180 Id::Number(v) => Ok(Id::Number(*v)),
181 Id::String(v) => Ok(Id::String(v.clone())),
182 Id::Array(v) => match v.compute(ctx, opt, txn, doc).await? {
183 Value::Array(v) => Ok(Id::Array(v)),
184 _ => unreachable!(),
185 },
186 Id::Object(v) => match v.compute(ctx, opt, txn, doc).await? {
187 Value::Object(v) => Ok(Id::Object(v)),
188 _ => unreachable!(),
189 },
190 Id::Generate(v) => match v {
191 Gen::Rand => Ok(Self::rand()),
192 Gen::Ulid => Ok(Self::ulid()),
193 Gen::Uuid => Ok(Self::uuid()),
194 },
195 }
196 }
197}