temper_core/
lib.rs

1use std::any::{Any, TypeId};
2use std::collections::VecDeque;
3use std::fmt;
4use std::mem::forget;
5use std::sync::{Arc, RwLock};
6
7pub mod float64;
8pub mod generator;
9pub use generator::{SafeGenerator, SafeGeneratorTrait};
10pub mod listed;
11pub use listed::{List, ListBuilder, Listed, ListedTrait, ToList, ToListBuilder, ToListed};
12pub mod mapped;
13pub use mapped::{mapped_to_list_with, Map, MapBuilder, Mapped, MappedTrait, Pair};
14pub mod promise;
15pub use promise::{
16    AsyncRunner, AsyncRunnerTrait, Promise, PromiseBuilder, SingleThreadAsyncRunner, Task,
17};
18pub mod string;
19pub use string::AsStr;
20
21// Accessors
22
23// Putting these in a separate scope avoids deadlock when in a context where
24// there's also a write to the same lock.
25
26pub fn read_locked<T: Clone>(x: &Arc<RwLock<T>>) -> T {
27    x.read().unwrap().clone()
28}
29
30// AnyValue
31
32#[macro_export]
33macro_rules! impl_any_value_trait { // for concrete types
34    // Two versions here. One for type args and one without.
35    ($type:ident<$($param:tt),*>, [$($target:ty),*]) => {
36        impl<$($param: Clone + Send + Sync + 'static),*> temper_core::AnyValueTrait for $type<$($param),*> {
37            fn cast(&self, type_id: std::any::TypeId) -> Option<Box<dyn std::any::Any>> {
38                match () {
39                    // Check the concrete type first, expecting it to be most common.
40                    _ if type_id == std::any::TypeId::of::<$type<$($param),*>>() => Some(Box::new(self.clone())),
41                    $(
42                        _ if type_id == std::any::TypeId::of::<$target>() => {
43                            Some(Box::new(<$target>::new(self.clone())))
44                        }
45                    )*
46                    _ => None,
47                }
48            }
49            fn is(&self, type_id: std::any::TypeId) -> bool {
50                type_id == std::any::TypeId::of::<$type<$($param),*>>()
51                $(|| type_id == std::any::TypeId::of::<$target>())*
52            }
53            fn ptr_id(&self) -> usize {
54                // And note that we implement ptr id only for concrete types. Abstracts delegate.
55                std::sync::Arc::as_ptr(&self.0) as usize
56            }
57        }
58        impl<$($param: Clone + Send + Sync + 'static),*> temper_core::AsAnyValue for $type<$($param),*> {
59            fn as_any_value(&self) -> temper_core::AnyValue {
60                temper_core::AnyValue::new(self.clone())
61            }
62        }
63    };
64    ($type:ident, [$($target:ty),*]) => {
65        impl temper_core::AnyValueTrait for $type {
66            fn cast(&self, type_id: std::any::TypeId) -> Option<Box<dyn std::any::Any>> {
67                match () {
68                    // Check the concrete type first, expecting it to be most common.
69                    _ if type_id == std::any::TypeId::of::<$type>() => Some(Box::new(self.clone())),
70                    $(
71                        _ if type_id == std::any::TypeId::of::<$target>() => {
72                            Some(Box::new(<$target>::new(self.clone())))
73                        }
74                    )*
75                    _ => None,
76                }
77            }
78            fn is(&self, type_id: std::any::TypeId) -> bool {
79                type_id == std::any::TypeId::of::<$type>()
80                $(|| type_id == std::any::TypeId::of::<$target>())*
81            }
82            fn ptr_id(&self) -> usize {
83                std::sync::Arc::as_ptr(&self.0) as usize
84            }
85        }
86        impl temper_core::AsAnyValue for $type {
87            fn as_any_value(&self) -> temper_core::AnyValue {
88                temper_core::AnyValue::new(self.clone())
89            }
90        }
91    };
92}
93
94#[macro_export]
95macro_rules! impl_any_value_trait_for_interface { // for abstract types
96    // Again, one for type args, and one without.
97    ($type:ident<$($param:tt),*>) => {
98        impl<$($param: Clone + Send + Sync + 'static),*> temper_core::AsAnyValue for $type<$($param),*> {
99            fn as_any_value(&self) -> temper_core::AnyValue {
100                self.0.as_any_value()
101            }
102        }
103    };
104    ($type:ty) => {
105        impl temper_core::AsAnyValue for $type {
106            fn as_any_value(&self) -> temper_core::AnyValue {
107                self.0.as_any_value()
108            }
109        }
110    };
111}
112
113pub trait AsAnyValue {
114    fn as_any_value(&self) -> AnyValue;
115}
116
117pub fn cast<T: 'static>(any_value: impl AsAnyValue) -> Option<T> {
118    let any_value = any_value.as_any_value();
119    let type_id = TypeId::of::<T>();
120    if type_id == TypeId::of::<AnyValue>() {
121        // We have an AnyValue, but we need to convince Rust that it's a T.
122        // This special case prevents needing to handle it in every impl.
123        let ptr = &any_value as *const AnyValue as *const T;
124        let result = Some(unsafe { ptr.read() });
125        // But don't decrement the instance above, since ptr read doesn't move.
126        forget(any_value);
127        return result;
128    }
129    let down = any_value.cast(type_id)?.downcast::<T>();
130    Some(*down.expect("valid cast result"))
131}
132
133pub fn is<T: 'static>(any_value: impl AsAnyValue) -> bool {
134    let type_id = TypeId::of::<T>();
135    if type_id == TypeId::of::<AnyValue>() {
136        return true;
137    }
138    any_value.as_any_value().is(type_id)
139}
140
141pub trait AnyValueTrait: Send + Sync {
142    // Supports also casting to supertraits of the base type.
143    fn cast(&self, type_id: TypeId) -> Option<Box<dyn Any>>;
144    fn is(&self, type_id: TypeId) -> bool;
145    fn ptr_id(&self) -> usize;
146}
147
148#[derive(Clone)]
149pub struct AnyValue(std::sync::Arc<dyn AnyValueTrait>);
150
151impl AnyValue {
152    pub fn new(selfish: impl AnyValueTrait + 'static) -> AnyValue {
153        AnyValue(std::sync::Arc::new(selfish))
154    }
155}
156
157impl AnyValueTrait for AnyValue {
158    fn cast(&self, type_id: TypeId) -> Option<Box<dyn Any>> {
159        self.0.cast(type_id)
160    }
161
162    fn is(&self, type_id: TypeId) -> bool {
163        self.0.is(type_id)
164    }
165
166    fn ptr_id(&self) -> usize {
167        self.0.ptr_id()
168    }
169}
170
171impl AsAnyValue for AnyValue {
172    fn as_any_value(&self) -> AnyValue {
173        self.clone()
174    }
175}
176
177impl std::ops::Deref for AnyValue {
178    type Target = dyn AnyValueTrait;
179    fn deref(&self) -> &Self::Target {
180        &(*self.0)
181    }
182}
183
184// AnyValue for ()
185
186impl AnyValueTrait for () {
187    fn cast(&self, type_id: TypeId) -> Option<Box<dyn Any>> {
188        match () {
189            _ if type_id == TypeId::of::<()>() => Some(Box::new(*self)),
190            _ => None,
191        }
192    }
193
194    fn is(&self, type_id: TypeId) -> bool {
195        type_id == TypeId::of::<()>()
196    }
197
198    fn ptr_id(&self) -> usize {
199        self as *const _ as usize
200    }
201}
202
203impl AsAnyValue for () {
204    fn as_any_value(&self) -> AnyValue {
205        AnyValue::new(*self)
206    }
207}
208
209// AnyValue for bool
210
211impl AnyValueTrait for bool {
212    fn cast(&self, type_id: TypeId) -> Option<Box<dyn Any>> {
213        match () {
214            _ if type_id == TypeId::of::<bool>() => Some(Box::new(*self)),
215            _ => None,
216        }
217    }
218
219    fn is(&self, type_id: TypeId) -> bool {
220        type_id == TypeId::of::<bool>()
221    }
222
223    fn ptr_id(&self) -> usize {
224        self as *const _ as usize
225    }
226}
227
228impl AsAnyValue for bool {
229    fn as_any_value(&self) -> AnyValue {
230        AnyValue::new(*self)
231    }
232}
233
234// AnyValue for f64
235
236impl AnyValueTrait for f64 {
237    fn cast(&self, type_id: TypeId) -> Option<Box<dyn Any>> {
238        match () {
239            _ if type_id == TypeId::of::<f64>() => Some(Box::new(*self)),
240            _ => None,
241        }
242    }
243
244    fn is(&self, type_id: TypeId) -> bool {
245        type_id == TypeId::of::<f64>()
246    }
247
248    fn ptr_id(&self) -> usize {
249        self as *const _ as usize
250    }
251}
252
253impl AsAnyValue for f64 {
254    fn as_any_value(&self) -> AnyValue {
255        AnyValue::new(*self)
256    }
257}
258
259// AnyValue for i32
260
261impl AnyValueTrait for i32 {
262    fn cast(&self, type_id: TypeId) -> Option<Box<dyn Any>> {
263        match () {
264            _ if type_id == TypeId::of::<i32>() => Some(Box::new(*self)),
265            _ => None,
266        }
267    }
268
269    fn is(&self, type_id: TypeId) -> bool {
270        type_id == TypeId::of::<i32>()
271    }
272
273    fn ptr_id(&self) -> usize {
274        // Shouldn't actually use this for ints. TODO Keep out of AnyValueTrait?
275        self as *const _ as usize
276    }
277}
278
279impl AsAnyValue for i32 {
280    fn as_any_value(&self) -> AnyValue {
281        AnyValue::new(*self)
282    }
283}
284
285// AnyValue for i64
286
287impl AnyValueTrait for i64 {
288    fn cast(&self, type_id: TypeId) -> Option<Box<dyn Any>> {
289        match () {
290            _ if type_id == TypeId::of::<i64>() => Some(Box::new(*self)),
291            _ => None,
292        }
293    }
294
295    fn is(&self, type_id: TypeId) -> bool {
296        type_id == TypeId::of::<i64>()
297    }
298
299    fn ptr_id(&self) -> usize {
300        // Shouldn't actually use this for ints. TODO Keep out of AnyValueTrait?
301        self as *const _ as usize
302    }
303}
304
305impl AsAnyValue for i64 {
306    fn as_any_value(&self) -> AnyValue {
307        AnyValue::new(*self)
308    }
309}
310
311// AnyValue for Arc<String>
312
313impl AnyValueTrait for Arc<String> {
314    fn cast(&self, type_id: TypeId) -> Option<Box<dyn Any>> {
315        match () {
316            _ if type_id == TypeId::of::<Arc<String>>() => Some(Box::new(self.clone())),
317            _ => None,
318        }
319    }
320
321    fn is(&self, type_id: TypeId) -> bool {
322        type_id == TypeId::of::<Arc<String>>()
323    }
324
325    fn ptr_id(&self) -> usize {
326        Arc::as_ptr(self) as usize
327    }
328}
329
330impl AsAnyValue for Arc<String> {
331    fn as_any_value(&self) -> AnyValue {
332        AnyValue::new(self.clone())
333    }
334}
335
336// Config
337
338#[derive(Clone)]
339pub struct Config {
340    runner: AsyncRunner,
341}
342
343impl Config {
344    pub fn runner(&self) -> &AsyncRunner {
345        &self.runner
346    }
347}
348
349impl Default for Config {
350    fn default() -> Self {
351        ConfigBuilder::default().build()
352    }
353}
354
355#[derive(Clone, Default)]
356pub struct ConfigBuilder {
357    runner: Option<AsyncRunner>,
358}
359
360impl ConfigBuilder {
361    pub fn build(self) -> Config {
362        Config {
363            runner: self
364                .runner
365                .unwrap_or_else(|| SingleThreadAsyncRunner::new()),
366        }
367    }
368
369    pub fn set_runner(&mut self, runner: AsyncRunner) -> &mut Self {
370        self.runner = Some(runner);
371        self
372    }
373}
374
375// DenseBitVector
376
377// TODO Could use bit-vec crate or other, but our current needs are small.
378// TODO And we might not want to expose some arbitrary 3rd-party crate for small needs.
379#[derive(Clone)]
380pub struct DenseBitVector(Arc<RwLock<Vec<BitChunk>>>);
381type BitChunk = u32;
382const BIT_CHUNK_SIZE: usize = 8 * std::mem::size_of::<BitChunk>();
383
384impl DenseBitVector {
385    pub fn with_capacity(capacity: i32) -> DenseBitVector {
386        let capacity: usize = capacity.try_into().unwrap();
387        let chunk_capacity = (capacity + BIT_CHUNK_SIZE - 1) / BIT_CHUNK_SIZE;
388        let bits = Vec::with_capacity(chunk_capacity);
389        DenseBitVector(Arc::new(RwLock::new(bits)))
390    }
391
392    fn split_index(index: i32) -> (usize, u32) {
393        let index: usize = index.try_into().unwrap();
394        (index / BIT_CHUNK_SIZE, 1 << (index % BIT_CHUNK_SIZE))
395    }
396
397    pub fn get(&self, index: i32) -> bool {
398        let (chunk_index, bit) = DenseBitVector::split_index(index);
399        let chunks = self.0.read().unwrap();
400        match chunks.get(chunk_index) {
401            Some(chunk) => (chunk & bit) != 0,
402            None => false,
403        }
404    }
405
406    pub fn set(&self, index: i32, value: bool) {
407        let (chunk_index, bit) = DenseBitVector::split_index(index);
408        let mut chunks = self.0.write().unwrap();
409        if chunk_index >= chunks.len() {
410            chunks.resize(chunk_index + 1, 0);
411        }
412        match value {
413            true => chunks[chunk_index] |= bit,
414            false => chunks[chunk_index] &= !bit,
415        }
416    }
417}
418
419// Deque
420
421pub type Deque<T> = Arc<RwLock<VecDeque<T>>>;
422
423pub mod deque {
424    use super::Deque;
425    use std::collections::VecDeque;
426    use std::sync::{Arc, RwLock};
427
428    pub fn new<T>() -> Deque<T> {
429        Arc::new(RwLock::new(VecDeque::new()))
430    }
431
432    pub fn add<T>(deque: &Deque<T>, value: T) {
433        deque.write().unwrap().push_back(value);
434    }
435
436    pub fn is_empty<T>(deque: &Deque<T>) -> bool {
437        deque.read().unwrap().is_empty()
438    }
439
440    pub fn remove_first<T>(deque: &Deque<T>) -> T {
441        deque.write().unwrap().pop_front().unwrap()
442    }
443}
444
445// Error
446
447#[derive(Clone, Debug)]
448pub struct Error(Option<Arc<dyn std::error::Error + Send + Sync>>);
449
450impl Error {
451    pub fn new() -> Self {
452        Error(None)
453    }
454
455    pub fn with_optional_message(message: Option<Arc<String>>) -> Self {
456        Error(message.map(|message| {
457            Arc::new(MessageError(message.clone())) as Arc<dyn std::error::Error + Send + Sync>
458        }))
459    }
460
461    pub fn with_source(source: Arc<dyn std::error::Error + Send + Sync>) -> Self {
462        Error(Some(source))
463    }
464}
465
466impl fmt::Display for Error {
467    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
468        write!(f, "{self}")
469    }
470}
471
472impl std::error::Error for Error {
473    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
474        self.0
475            .as_ref()
476            .map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
477    }
478}
479
480#[derive(Debug)]
481struct MessageError(Arc<String>);
482
483impl fmt::Display for MessageError {
484    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
485        write!(f, "{}", self.0)
486    }
487}
488
489impl std::error::Error for MessageError {}
490
491pub fn i32_to_usize(i: i32) -> Result<usize> {
492    i.try_into().map_err(|e| Error::with_source(Arc::new(e)))
493}
494
495pub fn usize_to_i32(u: usize) -> Result<i32> {
496    u.try_into().map_err(|e| Error::with_source(Arc::new(e)))
497}
498
499// Ignore
500
501pub fn ignore<T>(_: T) {}
502
503// Int
504
505pub fn int_div(a: i32, b: i32) -> Result<i32> {
506    if b == 0 {
507        // We want explicit errors for 0 but not for min / -1.
508        return Err(Error::new());
509    }
510    Ok(a.wrapping_div(b))
511}
512
513pub fn int_rem(a: i32, b: i32) -> Result<i32> {
514    if b == 0 {
515        // We want explicit errors for 0 but not for min % -1.
516        return Err(Error::new());
517    }
518    Ok(a.wrapping_rem(b))
519}
520
521pub fn int_to_string(i: i32, radix: Option<i32>) -> Arc<String> {
522    int64_to_string(i as i64, radix)
523}
524
525// Int64
526
527pub fn int64_div(a: i64, b: i64) -> Result<i64> {
528    if b == 0 {
529        // We want explicit errors for 0 but not for min / -1.
530        return Err(Error::new());
531    }
532    Ok(a.wrapping_div(b))
533}
534
535pub fn int64_rem(a: i64, b: i64) -> Result<i64> {
536    if b == 0 {
537        // We want explicit errors for 0 but not for min % -1.
538        return Err(Error::new());
539    }
540    Ok(a.wrapping_rem(b))
541}
542
543const MANTISSA_MAX_I64: i64 = 1i64 << 53;
544
545pub fn int64_to_float64(i: i64) -> Result<f64> {
546    match () {
547        _ if i > -MANTISSA_MAX_I64 && i < MANTISSA_MAX_I64 => Ok(i as f64),
548        _ => Err(Error::new()),
549    }
550}
551
552pub fn int64_to_int32(i: i64) -> Result<i32> {
553    match () {
554        _ if i >= (i32::MIN as i64) && i <= (i32::MAX as i64) => Ok(i as i32),
555        _ => Err(Error::new()),
556    }
557}
558
559pub fn int64_to_string(i: i64, radix: Option<i32>) -> Arc<String> {
560    let radix = TryInto::<u64>::try_into(radix.unwrap_or(10)).unwrap();
561    let negative = i < 0;
562    let mut i = (i as i128).abs() as u64;
563    let mut result = vec![];
564    loop {
565        let value = i % radix;
566        i /= radix;
567        // Panics on radix outside 2 through 36, which is ok.
568        result.push(char::from_digit(value as u32, radix as u32).unwrap() as u8);
569        if i == 0 {
570            break;
571        }
572    }
573    if negative {
574        result.push(b'-');
575    }
576    result.reverse();
577    Arc::new(String::from_utf8(result).unwrap())
578}
579
580// Result
581
582pub type Result<T> = std::result::Result<T, Error>;
583
584// String
585
586pub trait ToArcString {
587    fn to_arc_string(self) -> Arc<String>;
588}
589
590impl ToArcString for Arc<String> {
591    fn to_arc_string(self) -> Arc<String> {
592        self
593    }
594}
595
596impl ToArcString for char {
597    fn to_arc_string(self) -> Arc<String> {
598        Arc::new(self.to_string())
599    }
600}
601
602impl ToArcString for String {
603    fn to_arc_string(self) -> Arc<String> {
604        Arc::new(self)
605    }
606}
607
608impl ToArcString for &str {
609    fn to_arc_string(self) -> Arc<String> {
610        Arc::new(self.to_string())
611    }
612}