1use crate::{Error, Oop, Result, Session, Value};
2use std::collections::BTreeMap;
3
4pub const DEFAULT_BRIDGE_ROOT: &str = "GemStoneRsBridgeRoot";
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum BridgeKeyType {
8 String,
9 Symbol,
10}
11
12impl BridgeKeyType {
13 pub fn config_name(self) -> &'static str {
14 match self {
15 Self::String => "String",
16 Self::Symbol => "Symbol",
17 }
18 }
19}
20
21#[derive(Clone, Debug, Eq, PartialEq)]
22pub struct BridgeKey {
23 pub name: String,
24 pub key_type: BridgeKeyType,
25}
26
27impl BridgeKey {
28 pub fn string(name: impl Into<String>) -> Self {
29 Self {
30 name: name.into(),
31 key_type: BridgeKeyType::String,
32 }
33 }
34
35 pub fn symbol(name: impl Into<String>) -> Self {
36 Self {
37 name: name.into(),
38 key_type: BridgeKeyType::Symbol,
39 }
40 }
41
42 pub fn new(name: impl Into<String>, key_type: BridgeKeyType) -> Self {
43 Self {
44 name: name.into(),
45 key_type,
46 }
47 }
48
49 fn to_oop(&self, session: &mut Session) -> Result<Oop> {
50 match self.key_type {
51 BridgeKeyType::String => session.new_string(&self.name),
52 BridgeKeyType::Symbol => session.new_symbol(&self.name),
53 }
54 }
55}
56
57#[derive(Clone, Debug, PartialEq)]
58pub enum BridgeValue {
59 Nil,
60 Bool(bool),
61 SmallInt(i64),
62 String(String),
63 Symbol(String),
64 Oop(Oop),
65 Dictionary(BTreeMap<String, BridgeValue>),
66 KeyedDictionary(Vec<(BridgeKey, BridgeValue)>),
67 Array(Vec<BridgeValue>),
68}
69
70impl BridgeValue {
71 pub fn dictionary(entries: impl IntoIterator<Item = (String, BridgeValue)>) -> Self {
72 Self::Dictionary(entries.into_iter().collect())
73 }
74
75 pub fn keyed_dictionary(entries: impl IntoIterator<Item = (BridgeKey, BridgeValue)>) -> Self {
76 Self::KeyedDictionary(entries.into_iter().collect())
77 }
78
79 pub fn array(values: impl IntoIterator<Item = BridgeValue>) -> Self {
80 Self::Array(values.into_iter().collect())
81 }
82
83 pub fn to_oop(&self, session: &mut Session) -> Result<Oop> {
84 match self {
85 Self::Nil => Ok(session.nil_oop()),
86 Self::Bool(value) => Ok(session.bool_oop(*value)),
87 Self::SmallInt(value) => Ok(session.smallint_oop(*value)),
88 Self::String(value) => session.new_string(value),
89 Self::Symbol(value) => session.new_symbol(value),
90 Self::Oop(oop) => Ok(*oop),
91 Self::Dictionary(entries) => {
92 let dictionary = session.execute("Dictionary new")?;
93 session.identity_for_oop(dictionary);
94 for (key, value) in entries {
95 let key = session.new_string(key)?;
96 let value = value.to_oop(session)?;
97 session.perform_oop(dictionary, "at:put:", &[key, value])?;
98 }
99 Ok(dictionary)
100 }
101 Self::KeyedDictionary(entries) => {
102 let dictionary = session.execute("Dictionary new")?;
103 session.identity_for_oop(dictionary);
104 for (key, value) in entries {
105 let key = key.to_oop(session)?;
106 let value = value.to_oop(session)?;
107 session.perform_oop(dictionary, "at:put:", &[key, value])?;
108 }
109 Ok(dictionary)
110 }
111 Self::Array(values) => {
112 let array = session.execute(&format!("Array new: {}", values.len()))?;
113 session.identity_for_oop(array);
114 for (index, value) in values.iter().enumerate() {
115 let index = session.smallint_oop((index + 1) as i64);
116 let value = value.to_oop(session)?;
117 session.perform_oop(array, "at:put:", &[index, value])?;
118 }
119 Ok(array)
120 }
121 }
122 }
123}
124
125impl From<bool> for BridgeValue {
126 fn from(value: bool) -> Self {
127 Self::Bool(value)
128 }
129}
130
131impl From<i64> for BridgeValue {
132 fn from(value: i64) -> Self {
133 Self::SmallInt(value)
134 }
135}
136
137impl From<i32> for BridgeValue {
138 fn from(value: i32) -> Self {
139 Self::SmallInt(i64::from(value))
140 }
141}
142
143impl From<&str> for BridgeValue {
144 fn from(value: &str) -> Self {
145 Self::String(value.to_string())
146 }
147}
148
149impl From<String> for BridgeValue {
150 fn from(value: String) -> Self {
151 Self::String(value)
152 }
153}
154
155impl From<Oop> for BridgeValue {
156 fn from(value: Oop) -> Self {
157 Self::Oop(value)
158 }
159}
160
161impl From<Value> for BridgeValue {
162 fn from(value: Value) -> Self {
163 match value {
164 Value::Nil => Self::Nil,
165 Value::Bool(value) => Self::Bool(value),
166 Value::SmallInt(value) => Self::SmallInt(value),
167 Value::Char(value) => Self::String(value.to_string()),
168 Value::String(value) => Self::String(value),
169 Value::Oop(oop) => Self::Oop(oop),
170 }
171 }
172}
173
174pub trait BridgeFieldWrite {
175 fn to_bridge_field_value(&self) -> BridgeValue;
176}
177
178impl BridgeFieldWrite for bool {
179 fn to_bridge_field_value(&self) -> BridgeValue {
180 BridgeValue::Bool(*self)
181 }
182}
183
184impl BridgeFieldWrite for i64 {
185 fn to_bridge_field_value(&self) -> BridgeValue {
186 BridgeValue::SmallInt(*self)
187 }
188}
189
190impl BridgeFieldWrite for i32 {
191 fn to_bridge_field_value(&self) -> BridgeValue {
192 BridgeValue::SmallInt(i64::from(*self))
193 }
194}
195
196impl BridgeFieldWrite for String {
197 fn to_bridge_field_value(&self) -> BridgeValue {
198 BridgeValue::String(self.clone())
199 }
200}
201
202impl BridgeFieldWrite for &str {
203 fn to_bridge_field_value(&self) -> BridgeValue {
204 BridgeValue::String((*self).to_string())
205 }
206}
207
208impl BridgeFieldWrite for Oop {
209 fn to_bridge_field_value(&self) -> BridgeValue {
210 BridgeValue::Oop(*self)
211 }
212}
213
214impl BridgeFieldWrite for BridgeValue {
215 fn to_bridge_field_value(&self) -> BridgeValue {
216 self.clone()
217 }
218}
219
220impl<T: BridgeMapped> BridgeFieldWrite for T {
221 fn to_bridge_field_value(&self) -> BridgeValue {
222 self.to_bridge_value()
223 }
224}
225
226impl<T: BridgeFieldWrite> BridgeFieldWrite for Vec<T> {
227 fn to_bridge_field_value(&self) -> BridgeValue {
228 BridgeValue::array(self.iter().map(BridgeFieldWrite::to_bridge_field_value))
229 }
230}
231
232pub trait BridgeFieldRead: Sized {
233 fn read_bridge_field(
234 dictionary: &mut BridgeDictionary<'_>,
235 key: &str,
236 key_type: BridgeKeyType,
237 ) -> Result<Self> {
238 let oop = dictionary.at_oop_with_key_type(key, key_type)?;
239 Self::read_bridge_oop(
240 dictionary.session,
241 oop,
242 &BridgeFieldContext::new(key, key_type, Self::expected_type()),
243 )
244 }
245
246 fn read_bridge_oop(
247 session: &mut Session,
248 oop: Oop,
249 context: &BridgeFieldContext,
250 ) -> Result<Self>;
251
252 fn expected_type() -> &'static str;
253}
254
255impl BridgeFieldRead for String {
256 fn read_bridge_oop(
257 session: &mut Session,
258 oop: Oop,
259 _context: &BridgeFieldContext,
260 ) -> Result<Self> {
261 session.fetch_string(oop)
262 }
263
264 fn expected_type() -> &'static str {
265 "String"
266 }
267}
268
269impl BridgeFieldRead for i64 {
270 fn read_bridge_oop(
271 _session: &mut Session,
272 oop: Oop,
273 context: &BridgeFieldContext,
274 ) -> Result<Self> {
275 oop.as_smallint()
276 .ok_or_else(|| context.unexpected(format!("OOP {}", oop.raw())))
277 }
278
279 fn expected_type() -> &'static str {
280 "SmallInt"
281 }
282}
283
284impl BridgeFieldRead for bool {
285 fn read_bridge_oop(
286 _session: &mut Session,
287 oop: Oop,
288 context: &BridgeFieldContext,
289 ) -> Result<Self> {
290 oop.as_bool()
291 .ok_or_else(|| context.unexpected(format!("OOP {}", oop.raw())))
292 }
293
294 fn expected_type() -> &'static str {
295 "Bool"
296 }
297}
298
299impl BridgeFieldRead for Oop {
300 fn read_bridge_oop(
301 session: &mut Session,
302 oop: Oop,
303 _context: &BridgeFieldContext,
304 ) -> Result<Self> {
305 session.identity_for_oop(oop);
306 Ok(oop)
307 }
308
309 fn expected_type() -> &'static str {
310 "Oop"
311 }
312}
313
314impl<T: BridgeMapped> BridgeFieldRead for T {
315 fn read_bridge_oop(
316 session: &mut Session,
317 oop: Oop,
318 _context: &BridgeFieldContext,
319 ) -> Result<Self> {
320 let mut dictionary = BridgeDictionary::from_oop(session, oop);
321 T::from_bridge_dictionary(&mut dictionary)
322 }
323
324 fn expected_type() -> &'static str {
325 "Dictionary"
326 }
327}
328
329impl<T: BridgeFieldRead> BridgeFieldRead for Vec<T> {
330 fn read_bridge_oop(
331 session: &mut Session,
332 oop: Oop,
333 context: &BridgeFieldContext,
334 ) -> Result<Self> {
335 let size = session.fetch_size(oop)?;
336 if size < 0 {
337 return Err(Error::NegativeSize(size));
338 }
339 let mut values = Vec::with_capacity(size as usize);
340 for index in 1..=size {
341 let index_oop = session.smallint_oop(index);
342 let value_oop = session.perform_oop(oop, "at:", &[index_oop])?;
343 values.push(T::read_bridge_oop(session, value_oop, context)?);
344 }
345 Ok(values)
346 }
347
348 fn expected_type() -> &'static str {
349 "Array"
350 }
351}
352
353pub struct BridgeRoot<'a> {
354 session: &'a mut Session,
355 name: String,
356 oop: Oop,
357}
358
359impl<'a> BridgeRoot<'a> {
360 pub fn new(session: &'a mut Session) -> Result<Self> {
361 Self::named(session, DEFAULT_BRIDGE_ROOT)
362 }
363
364 pub fn named(session: &'a mut Session, name: impl Into<String>) -> Result<Self> {
365 let name = name.into();
366 let oop = match session.global_get(&name) {
367 Ok(oop) if oop != session.nil_oop() => oop,
368 Ok(_) | Err(_) => {
369 let root = session.execute("Dictionary new")?;
370 session.global_put(&name, root)?;
371 root
372 }
373 };
374 session.identity_for_oop(oop);
375 Ok(Self { session, name, oop })
376 }
377
378 pub fn name(&self) -> &str {
379 &self.name
380 }
381
382 pub fn oop(&self) -> Oop {
383 self.oop
384 }
385
386 pub fn identity_id(&self) -> usize {
387 self.session.identity_for_oop(self.oop)
388 }
389
390 pub fn put(&mut self, key: &str, value: impl Into<BridgeValue>) -> Result<Oop> {
391 self.put_with_key_type(key, BridgeKeyType::String, value)
392 }
393
394 pub fn put_with_key_type(
395 &mut self,
396 key: &str,
397 key_type: BridgeKeyType,
398 value: impl Into<BridgeValue>,
399 ) -> Result<Oop> {
400 let key_oop = BridgeKey::new(key, key_type).to_oop(self.session)?;
401 let value = value.into().to_oop(self.session)?;
402 self.session
403 .perform_oop(self.oop, "at:put:", &[key_oop, value])?;
404 self.session.identity_for_oop(value);
405 Ok(value)
406 }
407
408 pub fn put_mapped(&mut self, key: &str, value: &impl BridgeMapped) -> Result<Oop> {
409 self.put(key, value.to_bridge_value())
410 }
411
412 pub fn get_oop(&mut self, key: &str) -> Result<Oop> {
413 self.get_oop_with_key_type(key, BridgeKeyType::String)
414 }
415
416 pub fn get_oop_with_key_type(&mut self, key: &str, key_type: BridgeKeyType) -> Result<Oop> {
417 let key_oop = BridgeKey::new(key, key_type).to_oop(self.session)?;
418 let oop = self.session.perform_oop(self.oop, "at:", &[key_oop])?;
419 self.session.identity_for_oop(oop);
420 Ok(oop)
421 }
422
423 pub fn get_value(&mut self, key: &str) -> Result<Value> {
424 self.get_value_with_key_type(key, BridgeKeyType::String)
425 }
426
427 pub fn get_value_with_key_type(&mut self, key: &str, key_type: BridgeKeyType) -> Result<Value> {
428 let key_oop = BridgeKey::new(key, key_type).to_oop(self.session)?;
429 self.session.perform(self.oop, "at:", &[key_oop])
430 }
431
432 pub fn get_string(&mut self, key: &str) -> Result<String> {
433 let oop = self.get_oop(key)?;
434 self.session.fetch_string(oop)
435 }
436
437 pub fn get_smallint(&mut self, key: &str) -> Result<i64> {
438 match self.get_value(key)? {
439 Value::SmallInt(value) => Ok(value),
440 other => Err(unexpected_field(key, "SmallInt", other)),
441 }
442 }
443
444 pub fn get_bool(&mut self, key: &str) -> Result<bool> {
445 match self.get_value(key)? {
446 Value::Bool(value) => Ok(value),
447 other => Err(unexpected_field(key, "Bool", other)),
448 }
449 }
450
451 pub fn get_dictionary(&mut self, key: &str) -> Result<BridgeDictionary<'_>> {
452 let oop = self.get_oop(key)?;
453 Ok(BridgeDictionary::from_oop(self.session, oop))
454 }
455
456 pub fn get_mapped<T: BridgeMapped>(&mut self, key: &str) -> Result<T> {
457 let mut dictionary = self.get_dictionary(key)?;
458 T::from_bridge_dictionary(&mut dictionary)
459 }
460
461 pub fn remove(&mut self, key: &str) -> Result<Oop> {
462 self.remove_with_key_type(key, BridgeKeyType::String)
463 }
464
465 pub fn remove_with_key_type(&mut self, key: &str, key_type: BridgeKeyType) -> Result<Oop> {
466 let key_oop = BridgeKey::new(key, key_type).to_oop(self.session)?;
467 self.session.perform_oop(
468 self.oop,
469 "removeKey:ifAbsent:",
470 &[key_oop, self.session.nil_oop()],
471 )
472 }
473
474 pub fn commit(&mut self) -> Result<()> {
475 self.session.commit()
476 }
477
478 pub fn commit_with_retry(&mut self, retries: usize) -> Result<()> {
479 self.session.commit_with_retry(retries)
480 }
481
482 pub fn transaction<T>(
483 &mut self,
484 body: impl FnOnce(&mut BridgeRoot<'_>) -> Result<T>,
485 ) -> Result<T> {
486 match body(self) {
487 Ok(value) => {
488 self.commit()?;
489 Ok(value)
490 }
491 Err(err) => {
492 let _ = self.session.abort();
493 Err(err)
494 }
495 }
496 }
497}
498
499pub struct BridgeDictionary<'a> {
500 pub(crate) session: &'a mut Session,
501 oop: Oop,
502}
503
504impl<'a> BridgeDictionary<'a> {
505 pub fn from_oop(session: &'a mut Session, oop: Oop) -> Self {
506 session.identity_for_oop(oop);
507 Self { session, oop }
508 }
509
510 pub fn oop(&self) -> Oop {
511 self.oop
512 }
513
514 pub fn identity_id(&self) -> usize {
515 self.session.identity_for_oop(self.oop)
516 }
517
518 pub fn put(&mut self, key: &str, value: impl Into<BridgeValue>) -> Result<Oop> {
519 self.put_with_key_type(key, BridgeKeyType::String, value)
520 }
521
522 pub fn put_with_key_type(
523 &mut self,
524 key: &str,
525 key_type: BridgeKeyType,
526 value: impl Into<BridgeValue>,
527 ) -> Result<Oop> {
528 let key_oop = BridgeKey::new(key, key_type).to_oop(self.session)?;
529 let value = value.into().to_oop(self.session)?;
530 self.session
531 .perform_oop(self.oop, "at:put:", &[key_oop, value])?;
532 self.session.identity_for_oop(value);
533 Ok(value)
534 }
535
536 pub fn at_oop(&mut self, key: &str) -> Result<Oop> {
537 self.at_oop_with_key_type(key, BridgeKeyType::String)
538 }
539
540 pub fn at_oop_with_key_type(&mut self, key: &str, key_type: BridgeKeyType) -> Result<Oop> {
541 let key_oop = BridgeKey::new(key, key_type).to_oop(self.session)?;
542 let oop = self.session.perform_oop(self.oop, "at:", &[key_oop])?;
543 self.session.identity_for_oop(oop);
544 Ok(oop)
545 }
546
547 pub fn at_value(&mut self, key: &str) -> Result<Value> {
548 self.at_value_with_key_type(key, BridgeKeyType::String)
549 }
550
551 pub fn at_value_with_key_type(&mut self, key: &str, key_type: BridgeKeyType) -> Result<Value> {
552 let key_oop = BridgeKey::new(key, key_type).to_oop(self.session)?;
553 self.session.perform(self.oop, "at:", &[key_oop])
554 }
555
556 pub fn at_string(&mut self, key: &str) -> Result<String> {
557 self.at_string_with_key_type(key, BridgeKeyType::String)
558 }
559
560 pub fn at_string_with_key_type(
561 &mut self,
562 key: &str,
563 key_type: BridgeKeyType,
564 ) -> Result<String> {
565 let oop = self.at_oop_with_key_type(key, key_type)?;
566 self.session.fetch_string(oop)
567 }
568
569 pub fn at_smallint(&mut self, key: &str) -> Result<i64> {
570 self.at_smallint_with_key_type(key, BridgeKeyType::String)
571 }
572
573 pub fn at_smallint_with_key_type(&mut self, key: &str, key_type: BridgeKeyType) -> Result<i64> {
574 match self.at_value_with_key_type(key, key_type)? {
575 Value::SmallInt(value) => Ok(value),
576 other => Err(unexpected_field(key, "SmallInt", other)),
577 }
578 }
579
580 pub fn at_bool(&mut self, key: &str) -> Result<bool> {
581 self.at_bool_with_key_type(key, BridgeKeyType::String)
582 }
583
584 pub fn at_bool_with_key_type(&mut self, key: &str, key_type: BridgeKeyType) -> Result<bool> {
585 match self.at_value_with_key_type(key, key_type)? {
586 Value::Bool(value) => Ok(value),
587 other => Err(unexpected_field(key, "Bool", other)),
588 }
589 }
590
591 pub fn at_dictionary(&mut self, key: &str) -> Result<BridgeDictionary<'_>> {
592 self.at_dictionary_with_key_type(key, BridgeKeyType::String)
593 }
594
595 pub fn at_dictionary_with_key_type(
596 &mut self,
597 key: &str,
598 key_type: BridgeKeyType,
599 ) -> Result<BridgeDictionary<'_>> {
600 let oop = self.at_oop_with_key_type(key, key_type)?;
601 Ok(BridgeDictionary::from_oop(self.session, oop))
602 }
603
604 pub fn at_mapped<T: BridgeMapped>(&mut self, key: &str) -> Result<T> {
605 self.at_mapped_with_key_type(key, BridgeKeyType::String)
606 }
607
608 pub fn at_mapped_with_key_type<T: BridgeMapped>(
609 &mut self,
610 key: &str,
611 key_type: BridgeKeyType,
612 ) -> Result<T> {
613 let mut dictionary = self.at_dictionary_with_key_type(key, key_type)?;
614 T::from_bridge_dictionary(&mut dictionary)
615 }
616
617 pub fn at_vec<T: BridgeFieldRead>(&mut self, key: &str) -> Result<Vec<T>> {
618 self.at_vec_with_key_type(key, BridgeKeyType::String)
619 }
620
621 pub fn at_vec_with_key_type<T: BridgeFieldRead>(
622 &mut self,
623 key: &str,
624 key_type: BridgeKeyType,
625 ) -> Result<Vec<T>> {
626 BridgeFieldRead::read_bridge_field(self, key, key_type)
627 }
628}
629
630pub trait BridgeMapped: Sized {
631 fn to_bridge_value(&self) -> BridgeValue;
632
633 fn from_bridge_dictionary(dictionary: &mut BridgeDictionary<'_>) -> Result<Self>;
634}
635
636#[doc(hidden)]
637pub struct BridgeFieldContext {
638 key: String,
639 key_type: BridgeKeyType,
640 expected: &'static str,
641}
642
643impl BridgeFieldContext {
644 fn new(key: &str, key_type: BridgeKeyType, expected: &'static str) -> Self {
645 Self {
646 key: key.to_string(),
647 key_type,
648 expected,
649 }
650 }
651
652 fn unexpected(&self, actual: String) -> Error {
653 Error::Mapping {
654 field: format!("{} ({})", self.key, self.key_type.config_name()),
655 expected: self.expected,
656 actual,
657 }
658 }
659}
660
661fn unexpected_field(key: &str, expected: &'static str, actual: Value) -> Error {
662 Error::Mapping {
663 field: key.to_string(),
664 expected,
665 actual: format!("{actual:?}"),
666 }
667}